MySQL安全加固十大可直接落地的硬核操作
作者:做个文艺程序员
从账号权限最小化到SSL加密,构建生产环境基础防护层
适用于 MySQL 5.7 / 8.0 / 8.4
生产环境的 MySQL 安全加固是一个系统工程,绝不是仅仅设置一个强密码就能了事。本文梳理十项可直接落地的硬核操作,覆盖认证、网络、文件、日志、配置五大安全维度,帮助你构建生产环境的基础防护层。
一、账号权限最小化原则
⚠ 高危 权限管理 最高优先级
生产环境中,任何账号都不应拥有超过其职责所需的权限。常见误区是直接给应用账号赋予 ALL PRIVILEGES,一旦账号泄露后果不堪设想。
操作示例
-- 创建最小权限的应用账号(仅允许特定库的增删改查) CREATE USER 'app_user'@'192.168.1.%' IDENTIFIED BY 'StrongP@ss2024!'; GRANT SELECT, INSERT, UPDATE, DELETE ON your_database.* TO 'app_user'@'192.168.1.%'; FLUSH PRIVILEGES; -- 查看当前所有账号权限 SELECT user, host, authentication_string FROM mysql.user; -- 撤销危险权限(SUPER、FILE、PROCESS 等) REVOKE SUPER ON *.* FROM 'app_user'@'192.168.1.%';
💡 建议为 DBA、只读副本、监控账号分别创建独立用户,账号之间权限完全隔离。Host 字段优先使用精确 IP 或子网段,避免使用 % 通配符。
二、禁用或删除匿名账户与 test 库
⚠ 高危 初始化必做
MySQL 默认安装可能存在空密码的匿名账户和所有用户都可访问的 test 数据库。应在首次部署时立即清理。
操作示例
-- 查找并删除匿名账户 SELECT user, host FROM mysql.user WHERE user = ''; DELETE FROM mysql.user WHERE user = ''; -- 删除 test 数据库及其授权记录 DROP DATABASE IF EXISTS test; DELETE FROM mysql.db WHERE db = 'test' OR db = 'test\_%'; FLUSH PRIVILEGES;
# 推荐:使用官方安全初始化脚本(MySQL 8.0+) mysql_secure_installation
⚠️ 执行 mysql_secure_installation 可交互式完成以上清理步骤,同时设置 root 密码、禁止远程 root 登录,是新服务器上线必做项。
三、修改默认端口与绑定监听地址
网络防护 配置项
默认 3306 端口是全网自动化扫描的首要目标。将 MySQL 绑定到内网 IP,并修改为非标准端口,可有效降低被探测和攻击的概率。
my.cnf 配置
[mysqld] # 修改监听端口(避免使用 3306) port = 33066 # 仅绑定内网IP,禁止 0.0.0.0 监听 bind-address = 127.0.0.1 # 若需多网卡绑定(MySQL 8.0.13+) # bind-address = 192.168.1.100,127.0.0.1 # 禁用 MySQL X Protocol(若不使用) mysqlx = 0
防火墙规则(firewalld)
# 仅允许应用服务器网段访问数据库端口 firewall-cmd --permanent --add-rich-rule=' rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="33066" accept' firewall-cmd --reload
四、强化密码策略与账号锁定
⚠ 高危 认证安全
MySQL 8.0 引入了 validate_password 组件和失败登录追踪功能,可有效对抗暴力破解。建议同时配置密码过期策略。
安装密码验证组件并配置策略
-- 安装密码验证组件(MySQL 8.0+) INSTALL COMPONENT 'file://component_validate_password'; -- 配置密码强度策略 SET GLOBAL validate_password.policy = STRONG; SET GLOBAL validate_password.length = 12; SET GLOBAL validate_password.mixed_case_count = 1; SET GLOBAL validate_password.special_char_count = 1; SET GLOBAL validate_password.number_count = 1; -- 失败登录追踪:连续失败3次锁定账号1天 ALTER USER 'app_user'@'%' FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 1; -- 设置密码90天强制过期 ALTER USER 'app_user'@'%' PASSWORD EXPIRE INTERVAL 90 DAY;
✅ MySQL 8.0 默认认证插件已从 mysql_native_password 切换为更安全的 caching_sha2_password,无需额外配置,但要确保客户端驱动版本支持该插件。
五、启用 SSL/TLS 加密传输
⚠ 高危 传输安全
MySQL 客户端与服务端之间的连接在未启用 SSL 时以明文传输,密码和业务数据均存在被中间人嗅探的风险。生产环境应强制启用 SSL 连接。
第一步:生成证书
# MySQL 自带工具一键生成 CA + 服务端 + 客户端证书 mysql_ssl_rsa_setup --datadir=/var/lib/mysql # 验证生成的证书文件 ls /var/lib/mysql/*.pem # ca.pem ca-key.pem server-cert.pem server-key.pem # client-cert.pem client-key.pem
第二步:my.cnf 配置
[mysqld] ssl-ca = /var/lib/mysql/ca.pem ssl-cert = /var/lib/mysql/server-cert.pem ssl-key = /var/lib/mysql/server-key.pem # 强制所有连接使用 TLS 1.2+ tls_version = TLSv1.2,TLSv1.3 [client] ssl-ca = /var/lib/mysql/ca.pem ssl-cert = /var/lib/mysql/client-cert.pem ssl-key = /var/lib/mysql/client-key.pem
第三步:对账号强制 SSL
-- 对特定账号强制 SSL(推荐) ALTER USER 'app_user'@'%' REQUIRE SSL; -- 更严格:要求双向证书认证(适合 DBA 账号) ALTER USER 'dba_user'@'%' REQUIRE X509; -- 验证 SSL 是否生效 SHOW VARIABLES LIKE '%ssl%'; SHOW STATUS LIKE 'Ssl_cipher';
六、开启审计日志
合规审计 可观测性
安全事件发生后,审计日志是还原攻击路径的唯一可靠手段。MySQL Enterprise Edition 提供原生审计插件;社区版可通过开启 General Log 或安装第三方插件实现。
my.cnf 配置(社区版推荐方案)
[mysqld] # 慢查询日志(推荐常驻开启) slow_query_log = 1 slow_query_log_file = /var/log/mysql/slow.log long_query_time = 2 # Binary Log(复制与时间点恢复的基础) log_bin = /var/log/mysql/mysql-bin binlog_format = ROW expire_logs_days = 7 # 通用查询日志(生产环境慎用,性能影响大,可临时开启排查) # general_log = 1 # general_log_file = /var/log/mysql/general.log
安装审计插件(Enterprise Edition)
-- MySQL Enterprise Audit Plugin INSTALL PLUGIN audit_log SONAME 'audit_log.so'; SET GLOBAL audit_log_policy = 'ALL'; SET GLOBAL audit_log_format = 'JSON'; SET GLOBAL audit_log_file = '/var/log/mysql/audit.log';
💡 Binary Log(binlog)是数据安全的核心,既支持主从复制,也支持基于时间点的精确恢复(PITR)。生产环境务必开启,且日志文件应存储在独立磁盘分区。
七、限制 LOAD DATA INFILE 与 FILE 权限
⚠ 高危 文件安全
LOAD DATA INFILE 可读取服务器本地文件,FILE 权限允许将数据导出到服务器文件系统。这两个功能是 SQL 注入攻击的高价值目标,若不使用应完全禁用。
my.cnf 配置
[mysqld] # 禁止 LOAD DATA INFILE 访问服务端文件 local_infile = 0 # 限制 SELECT INTO OUTFILE 只能写入指定目录 secure_file_priv = /var/lib/mysql-files # ❌ 以下配置极度危险,绝对禁止! # secure_file_priv = (空值 = 允许写入任意路径)
检查并撤销 FILE 权限
-- 确认没有普通账号拥有 FILE 权限 SELECT user, host, File_priv FROM mysql.user WHERE File_priv = 'Y' AND user != 'root'; -- 撤销 FILE 权限 REVOKE FILE ON *.* FROM 'some_user'@'%';
八、关闭不必要的功能与插件
系统加固 配置项
每个启用的功能和插件都是潜在的攻击面。关闭 symbolic-links、禁用不使用的存储引擎和协议,是攻击面最小化原则的直接体现。
my.cnf 配置
[mysqld] # 禁止符号链接(防止绕过权限访问文件系统) symbolic-links = 0 # 禁用 FEDERATED 存储引擎(若不使用) skip-federated # 禁止 DNS 反向解析(提升连接性能,防止 DNS 欺骗) skip_name_resolve = 1 # 禁止 SHOW DATABASES 暴露所有库名给普通用户 skip-show-database # 限制最大连接数,防止连接耗尽攻击(DoS) max_connections = 500 max_connect_errors = 10
⚠️ 启用 skip_name_resolve 后,GRANT 语句中的 host 只能填写 IP 地址,不能写域名。需提前将所有已有账号的 host 字段更新为 IP 格式。
九、定期备份 + 权限完整性校验
运维 数据保护
备份本身不足够,未经验证的备份等于没有备份。同时应定期审查账号权限分布,发现异常账号和权限漂移。
自动备份脚本
#!/bin/bash # 建议配合 crontab 每日凌晨执行 DATE=$(date +%Y%m%d_%H%M%S) BACKUP_DIR=/backup/mysql # 使用 mysqldump 全量备份 mysqldump \ --single-transaction \ --flush-logs \ --master-data=2 \ --all-databases \ -u backup_user -p'BackupP@ss!' \ | gzip > $BACKUP_DIR/full_$DATE.sql.gz # 验证备份文件大小(小于 1KB 视为异常) FILESIZE=$(stat -c%s "$BACKUP_DIR/full_$DATE.sql.gz") [ "$FILESIZE" -lt 1024 ] && echo "[ERROR] 备份文件异常!请检查!" # 清理7天前的旧备份 find $BACKUP_DIR -name "*.sql.gz" -mtime +7 -delete
权限审计 SQL
-- 定期执行:找出所有拥有全局高危权限的账号
SELECT user, host,
Super_priv, Grant_priv, File_priv,
Shutdown_priv, Process_priv
FROM mysql.user
WHERE Super_priv = 'Y'
OR Grant_priv = 'Y'
OR File_priv = 'Y';十、安全配置文件基线收尾
基线配置 收尾
将前九项加固操作整合为统一的配置基线,便于版本控制与合规审计。以下是可直接用于生产的 my.cnf 安全基线模板。
生产安全基线 my.cnf
[mysqld] # ===== 网络安全 ===== bind-address = 127.0.0.1 port = 33066 skip_name_resolve = 1 mysqlx = 0 max_connections = 500 max_connect_errors = 10 # ===== 认证与加密 ===== ssl-ca = /var/lib/mysql/ca.pem ssl-cert = /var/lib/mysql/server-cert.pem ssl-key = /var/lib/mysql/server-key.pem tls_version = TLSv1.2,TLSv1.3 # ===== 文件系统隔离 ===== local_infile = 0 secure_file_priv = /var/lib/mysql-files symbolic-links = 0 # ===== 功能最小化 ===== skip-federated skip-show-database # ===== 日志 ===== slow_query_log = 1 slow_query_log_file = /var/log/mysql/slow.log long_query_time = 2 log_bin = /var/log/mysql/mysql-bin binlog_format = ROW expire_logs_days = 7
配置生效验证
# 重启 MySQL 服务 systemctl restart mysqld # 验证关键参数是否生效 mysqladmin -u root -p variables | grep -E \ 'ssl|local_infile|secure_file|skip_name|max_conn|port' # 检查数据库完整性 mysqlcheck --all-databases -u root -p
✅ 配置完成后,建议使用 MySQLTuner 或 Percona Security Check 对实例进行全面安全扫描,输出安全评分报告,留存作为合规依据。
十大加固操作总结
| # | 操作 | 安全维度 | 优先级 |
|---|---|---|---|
| 1 | 账号权限最小化 | 认证安全 | 🔴 最高 |
| 2 | 清理匿名账户 / test 库 | 认证安全 | 🔴 最高 |
| 3 | 修改端口 + 绑定内网 IP | 网络防护 | 🟠 高 |
| 4 | 密码策略 + 登录锁定 | 认证安全 | 🔴 最高 |
| 5 | SSL/TLS 加密传输 | 传输安全 | 🔴 最高 |
| 6 | 审计日志 + Binlog | 合规审计 | 🟠 高 |
| 7 | 禁用 FILE / LOAD DATA | 文件安全 | 🔴 最高 |
| 8 | 关闭不必要功能插件 | 系统加固 | 🟡 中 |
| 9 | 定期备份 + 权限校验 | 数据保护 | 🟠 高 |
| 10 | 安全基线配置统一管理 | 配置管理 | 🟡 中 |
到此这篇关于MySQL安全加固十大硬核操作方法的文章就介绍到这了,更多相关MySQL安全加固操作内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
