6.3.5 访问控制与网络安全配置

本节围绕 MySQL 的访问控制与网络安全配置展开,目标是最小化暴露面、限制访问路径、提升传输安全与可审计性。

原理草图:访问控制分层与数据通路#

文章图片

访问控制原则与边界#

  • 暴露面最小化:仅开放必要端口,限制监听地址与网络访问范围。
  • 分层防护:操作系统防火墙、数据库访问控制、网络隔离与应用侧访问限制同时生效。
  • 最小权限:数据库用户权限与网络访问权限同步收敛。

绑定地址与监听限制#

配置示例:仅允许业务网段访问

# /etc/my.cnf
[mysqld]
bind-address = 10.0.0.10
port = 3306

生效与验证

# 重启 MySQL
systemctl restart mysqld

# 验证监听地址
ss -lntp | grep 3306
# 期望输出包含:10.0.0.10:3306

命令说明
- bind-address:限制 mysqld 监听地址,避免对公网/IP全网段暴露。
- ss -lntp:查看监听端口与进程绑定情况。

账户访问来源限制#

创建用户并限制来源网段

-- 仅允许 10.0.0.0/24 访问
CREATE USER 'app_user'@'10.0.0.%' IDENTIFIED BY 'StrongPass!2024';
GRANT SELECT,INSERT,UPDATE,DELETE ON appdb.* TO 'app_user'@'10.0.0.%';
FLUSH PRIVILEGES;

禁止通配来源示例

-- 不推荐:允许任意来源
-- CREATE USER 'app_user'@'%' IDENTIFIED BY 'StrongPass!2024';

命令说明
- 'user'@'host':host 控制来源地址,可精确到 IP 或网段。
- FLUSH PRIVILEGES:立即刷新授权表。

网络层安全配置#

Linux 防火墙(firewalld)仅放行业务网段

# 仅允许 10.0.0.0/24 访问 3306
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" \
source address="10.0.0.0/24" port port="3306" protocol="tcp" accept'

# 拒绝其他访问
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" \
port port="3306" protocol="tcp" drop'

firewall-cmd --reload

验证

# 查看生效规则
firewall-cmd --list-all

命令说明
- --add-rich-rule:按来源与端口精细控制访问。
- 先允许白名单,再对外全部拒绝。

连接加密与 SSL#

生成证书(示例)

# 创建 CA
openssl genrsa 2048 > ca-key.pem
openssl req -new -x509 -nodes -days 3650 -key ca-key.pem -out ca.pem -subj "/CN=MySQL-CA"

# 创建服务端证书
openssl req -newkey rsa:2048 -days 3650 -nodes -keyout server-key.pem -out server-req.pem -subj "/CN=mysql-server"
openssl x509 -req -in server-req.pem -days 3650 -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem

# 设置权限
chmod 600 *-key.pem

MySQL 启用 TLS

# /etc/my.cnf
[mysqld]
ssl-ca = /etc/mysql/ssl/ca.pem
ssl-cert = /etc/mysql/ssl/server-cert.pem
ssl-key = /etc/mysql/ssl/server-key.pem

强制某用户加密连接

ALTER USER 'app_user'@'10.0.0.%' REQUIRE SSL;

客户端验证

mysql -h 10.0.0.10 -u app_user -p \
  --ssl-ca=/etc/mysql/ssl/ca.pem \
  --ssl-mode=REQUIRED

预期效果
- 连接成功后 \s 显示 SSL: Cipher in use 字样。

远程访问与管理控制#

禁止 root 远程登录

-- 删除远程 root(如存在)
DROP USER IF EXISTS 'root'@'%';
DROP USER IF EXISTS 'root'@'10.0.0.%';

仅允许本地维护

CREATE USER IF NOT EXISTS 'root'@'localhost' IDENTIFIED BY 'LocalRoot!2024';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;

应用侧访问控制#

连接数与超时建议

# /etc/my.cnf
[mysqld]
max_connections = 500
wait_timeout = 300
connect_timeout = 10

命令说明
- max_connections:限制并发连接上限,防止连接耗尽。
- wait_timeout:空闲连接超时释放资源。

排错与验证清单#

问题1:应用连接被拒绝

# 检查防火墙是否阻断
firewall-cmd --list-all | grep 3306

# 检查监听地址
ss -lntp | grep 3306

问题2:用户被拒绝

-- 检查授权来源
SELECT user, host FROM mysql.user WHERE user='app_user';

问题3:SSL 连接失败

-- 查看服务器端 SSL 状态
SHOW VARIABLES LIKE 'have_ssl';
SHOW VARIABLES LIKE 'ssl_%';

预期
- have_sslYES,且 ssl_% 路径正确。

练习#

  1. bind-address0.0.0.0 改为 10.0.0.10,重启后验证监听地址。
  2. 创建 report_user 仅允许 10.0.0.20 访问,并验证从其他 IP 连接失败。
  3. app_user 启用 REQUIRE SSL,验证非 SSL 连接被拒绝。
  4. 使用 firewalld 仅放行 10.0.0.0/24,并从非白名单主机测试连接失败。
  5. 清理所有 user@'%' 且高权限账户,输出变更清单。