外观
MySQL 安全加固建议
权限管理
最小权限原则
加固措施:
创建专用用户:
- 为每个应用创建独立的数据库用户
- 为管理任务创建专用管理员用户
- 避免使用 root 用户进行日常操作
精细权限控制:
- 只授予用户必要的权限
- 使用最小权限组合
- 定期审查和回收不必要的权限
权限分配示例:
sql
-- 创建应用用户(只读权限)
CREATE USER 'app_read'@'%' IDENTIFIED BY 'strong_password';
GRANT SELECT ON app_db.* TO 'app_read'@'%';
-- 创建应用用户(读写权限)
CREATE USER 'app_write'@'%' IDENTIFIED BY 'strong_password';
GRANT SELECT, INSERT, UPDATE, DELETE ON app_db.* TO 'app_write'@'%';
-- 创建管理员用户(有限管理权限)
CREATE USER 'db_admin'@'localhost' IDENTIFIED BY 'strong_password';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, INDEX ON *.* TO 'db_admin'@'localhost';角色管理
加固措施:
使用角色管理权限:
- 创建功能角色
- 将权限分配给角色
- 将角色分配给用户
角色管理示例:
sql
-- 创建只读角色
CREATE ROLE 'read_only';
GRANT SELECT ON *.* TO 'read_only';
-- 创建读写角色
CREATE ROLE 'read_write';
GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO 'read_write';
-- 分配角色给用户
GRANT 'read_only' TO 'app_user'@'%';
SET DEFAULT ROLE 'read_only' TO 'app_user'@'%';权限审计
加固措施:
定期权限审计:
- 审查用户权限
- 检查未使用的用户
- 验证权限分配是否合理
审计工具:
- 使用
SHOW GRANTS查看用户权限 - 使用
mysql.user表分析用户信息 - 使用
mysql.role_edges查看角色分配
- 使用
审计示例:
sql
-- 查看用户权限
SHOW GRANTS FOR 'app_user'@'%';
-- 查看所有用户
SELECT user, host FROM mysql.user;
-- 查看角色分配
SELECT FROM_USER, TO_USER, FROM_HOST, TO_HOST
FROM mysql.role_edges;密码策略
密码强度要求
加固措施:
设置密码验证插件:
- 启用
validate_password插件 - 配置密码强度要求
- 定期强制密码更改
- 启用
密码策略配置:
sql
-- 安装并启用密码验证插件
INSTALL PLUGIN validate_password SONAME 'validate_password.so';
-- 配置密码强度要求
SET GLOBAL validate_password_length = 12;
SET GLOBAL validate_password_number_count = 1;
SET GLOBAL validate_password_special_char_count = 1;
SET GLOBAL validate_password_mixed_case_count = 1;
SET GLOBAL validate_password_policy = 'STRONG';
-- 设置密码过期时间(90天)
SET GLOBAL default_password_lifetime = 90;密码管理
加固措施:
安全密码存储:
- 使用
caching_sha2_password认证插件 - 避免明文存储密码
- 定期更新密码哈希
- 使用
密码轮换:
- 实施密码轮换策略
- 记录密码更改历史
- 防止密码重用
密码管理示例:
sql
-- 更改用户密码
ALTER USER 'app_user'@'%' IDENTIFIED BY 'new_strong_password';
-- 强制用户下次登录时更改密码
ALTER USER 'app_user'@'%' PASSWORD EXPIRE;
-- 禁用密码重用
SET GLOBAL password_history = 5;认证插件
加固措施:
使用安全认证插件:
- 优先使用
caching_sha2_password - 避免使用
mysql_native_password - 配置认证插件参数
- 优先使用
认证插件配置:
sql
-- 设置默认认证插件
SET GLOBAL default_authentication_plugin = 'caching_sha2_password';
-- 为用户指定认证插件
CREATE USER 'app_user'@'%'
IDENTIFIED WITH caching_sha2_password BY 'strong_password';网络安全
连接控制
加固措施:
限制网络访问:
- 使用防火墙限制 MySQL 端口(3306)
- 配置
bind-address限制监听地址 - 使用
skip-networking禁用网络访问(仅本地访问时)
网络配置:
sql
-- 限制监听地址(仅允许本地访问)
bind-address = 127.0.0.1
-- 或允许特定IP访问
bind-address = 192.168.1.100
-- 禁用网络访问(仅本地socket)
skip-networkingSSL/TLS 加密
加固措施:
启用 SSL/TLS:
- 配置 SSL 证书
- 强制使用 SSL 连接
- 验证客户端证书
SSL 配置:
sql
-- SSL 配置
ssl-ca = /path/to/ca-cert.pem
ssl-cert = /path/to/server-cert.pem
ssl-key = /path/to/server-key.pem
-- 强制使用 SSL
require_secure_transport = ON
-- 为用户要求 SSL
CREATE USER 'app_user'@'%'
IDENTIFIED BY 'strong_password'
REQUIRE SSL;
-- 为用户要求特定的 SSL 证书
CREATE USER 'secure_user'@'%'
IDENTIFIED BY 'strong_password'
REQUIRE X509;连接池安全
加固措施:
连接池配置:
- 设置合理的连接超时
- 配置连接验证
- 限制最大连接数
连接池参数:
sql
-- 设置连接超时
SET GLOBAL wait_timeout = 3600;
SET GLOBAL interactive_timeout = 3600;
-- 限制最大连接数
SET GLOBAL max_connections = 500;
-- 设置连接错误限制
SET GLOBAL max_connect_errors = 100;数据加密
静态数据加密
加固措施:
表空间加密:
- 启用 InnoDB 表空间加密
- 配置加密密钥管理
- 加密现有表空间
表空间加密配置:
sql
-- 启用表空间加密
SET GLOBAL innodb_encrypt_tables = ON;
SET GLOBAL innodb_encrypt_log = ON;
-- 配置加密算法
SET GLOBAL innodb_crypto_algorithm = 'AES_256_GCM';
-- 加密现有表
ALTER TABLE sensitive_data ENCRYPTION='Y';
-- 创建加密表
CREATE TABLE encrypted_table (
id INT PRIMARY KEY,
data VARCHAR(255)
) ENCRYPTION='Y';传输加密
加固措施:
使用 SSL/TLS 传输加密:
- 配置服务器 SSL 证书
- 强制客户端使用 SSL
- 验证 SSL 连接
传输加密验证:
sql
-- 验证 SSL 状态
SHOW VARIABLES LIKE '%ssl%';
-- 查看当前连接的 SSL 状态
SHOW STATUS LIKE 'Ssl_cipher';
-- 验证 SSL 连接
SELECT * FROM performance_schema.threads
WHERE processlist_id = CONNECTION_ID()
AND ssl_version IS NOT NULL;应用层加密
加固措施:
敏感数据加密:
- 在应用层加密敏感数据
- 使用安全的加密算法
- 安全管理加密密钥
应用层加密示例(Python):
python
import cryptography
from cryptography.fernet import Fernet
# 生成密钥
key = Fernet.generate_key()
f = Fernet(key)
# 加密数据
sensitive_data = "credit_card_number"
encrypted_data = f.encrypt(sensitive_data.encode())
# 解密数据
decrypted_data = f.decrypt(encrypted_data).decode()审计日志
审计日志配置
加固措施:
启用审计日志:
- 配置 MySQL 审计日志
- 设置审计日志格式
- 配置审计日志轮换
审计日志配置:
sql
-- 启用通用查询日志(仅用于调试)
SET GLOBAL general_log = ON;
SET GLOBAL general_log_file = '/var/log/mysql/general.log';
-- 启用错误日志
SET GLOBAL log_error = '/var/log/mysql/error.log';
-- 启用二进制日志(用于复制和恢复)
SET GLOBAL log_bin = '/var/log/mysql/binlog';
SET GLOBAL binlog_format = 'ROW';
-- 启用慢查询日志
SET GLOBAL slow_query_log = ON;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow-query.log';
SET GLOBAL long_query_time = 1;审计插件
加固措施:
使用审计插件:
- 安装 MySQL Enterprise Audit 插件
- 或使用 MariaDB Audit Plugin
- 配置审计规则
审计插件配置:
sql
-- 安装 MariaDB Audit Plugin
INSTALL PLUGIN server_audit SONAME 'server_audit.so';
-- 配置审计事件
SET GLOBAL server_audit_events = 'CONNECT,QUERY,TABLE';
-- 配置审计日志文件
SET GLOBAL server_audit_log_file = '/var/log/mysql/audit.log';
-- 启用审计插件
SET GLOBAL server_audit_logging = ON;日志管理
加固措施:
日志安全管理:
- 限制日志文件权限
- 加密敏感日志
- 定期备份日志
- 实施日志轮换
日志权限设置:
bash
# 设置日志文件权限
chmod 640 /var/log/mysql/*.log
chown mysql:mysql /var/log/mysql/*.log
# 配置日志轮换(/etc/logrotate.d/mysql)
/var/log/mysql/*.log {
daily
rotate 7
compress
delaycompress
missingok
create 640 mysql mysql
postrotate
/usr/bin/mysqladmin flush-logs
endscript
}系统安全
文件系统安全
加固措施:
文件权限:
- 限制 MySQL 数据目录权限
- 保护配置文件
- 限制日志文件访问
文件权限设置:
bash
# 设置数据目录权限
chmod 750 /var/lib/mysql
chown mysql:mysql /var/lib/mysql
# 设置配置文件权限
chmod 644 /etc/my.cnf
chown mysql:mysql /etc/my.cnf
# 设置日志目录权限
chmod 750 /var/log/mysql
chown mysql:mysql /var/log/mysql操作系统安全
加固措施:
操作系统加固:
- 定期更新操作系统
- 安装安全补丁
- 配置防火墙
- 禁用不必要的服务
防火墙配置:
bash
# 配置防火墙允许 MySQL 端口
ufw allow 3306/tcp
# 或使用 iptables
iptables -A INPUT -p tcp --dport 3306 -s 192.168.1.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 3306 -j DROP进程安全
加固措施:
运行用户:
- 使用专用的 MySQL 用户运行进程
- 避免以 root 用户运行
- 限制进程权限
进程安全配置:
bash
# 检查 MySQL 运行用户
ps aux | grep mysql
# 确保 MySQL 以 mysql 用户运行
# 在 my.cnf 中配置
user = mysql网络安全
防火墙配置
加固措施:
配置防火墙:
- 限制 MySQL 端口访问
- 只允许特定 IP 访问
- 启用防火墙日志
防火墙规则:
bash
# 使用 ufw 配置
ufw allow from 192.168.1.0/24 to any port 3306
# 使用 iptables 配置
iptables -A INPUT -p tcp --dport 3306 -s 192.168.1.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 3306 -j LOG --log-prefix "MySQL Access Denied: "
iptables -A INPUT -p tcp --dport 3306 -j DROP网络隔离
加固措施:
网络隔离:
- 使用 VLAN 隔离数据库网络
- 实施网络访问控制
- 使用专用网络连接
连接控制:
sql
-- 限制用户访问主机
CREATE USER 'app_user'@'192.168.1.%' IDENTIFIED BY 'password';
-- 限制管理员只能从本地访问
CREATE USER 'admin'@'localhost' IDENTIFIED BY 'password';连接验证
加固措施:
连接验证:
- 实施连接限制
- 配置连接超时
- 监控异常连接
连接限制:
sql
-- 设置连接错误限制
SET GLOBAL max_connect_errors = 100;
-- 设置连接超时
SET GLOBAL wait_timeout = 3600;
SET GLOBAL interactive_timeout = 3600;
-- 限制每个用户的连接数
SET GLOBAL max_user_connections = 100;安全更新和补丁
定期更新
加固措施:
定期更新 MySQL:
- 关注 MySQL 安全公告
- 定期应用安全补丁
- 测试更新后再部署
更新流程:
- 备份数据库
- 在测试环境测试更新
- 计划更新时间窗口
- 执行更新
- 验证更新结果
漏洞管理
加固措施:
漏洞扫描:
- 定期扫描 MySQL 漏洞
- 使用专业漏洞扫描工具
- 及时修复发现的漏洞
漏洞监控:
- 订阅 MySQL 安全公告
- 关注 CVE 数据库
- 参与安全社区
漏洞扫描工具:
- OpenVAS
- Nessus
- MySQL Enterprise Monitor
应急响应
安全事件处理
加固措施:
安全事件响应计划:
- 制定安全事件响应流程
- 明确角色和责任
- 建立通信渠道
- 定期演练
事件响应步骤:
- 检测和识别安全事件
- 遏制事件影响
- 消除事件根源
- 恢复系统正常运行
- 分析和学习
备份和恢复
加固措施:
定期备份:
- 执行完整备份
- 执行增量备份
- 验证备份完整性
备份策略:
bash
# 完整备份
mysqldump --all-databases --single-transaction --routines --triggers > full_backup.sql
# 增量备份(使用二进制日志)
mysqlbinlog --start-position=107 --stop-position=200 /var/log/mysql/binlog.000001 > incremental_backup.sql
# 验证备份
mysqlcheck --all-databases- 恢复测试:
- 定期测试备份恢复
- 验证恢复时间
- 确保恢复数据完整
安全最佳实践
配置最佳实践
推荐配置:
- 安全配置示例:
ini
# MySQL 安全配置
[mysqld]
# 基础安全
user = mysql
bind-address = 127.0.0.1
skip-networking = 0
# 权限管理
local_infile = 0
secure_file_priv = /tmp
# 密码策略
validate_password_length = 12
validate_password_policy = STRONG
default_password_lifetime = 90
password_history = 5
# 审计日志
general_log = 0
slow_query_log = 1
long_query_time = 1
log_error = /var/log/mysql/error.log
# SSL/TLS
ssl-ca = /etc/mysql/ssl/ca-cert.pem
ssl-cert = /etc/mysql/ssl/server-cert.pem
ssl-key = /etc/mysql/ssl/server-key.pem
require_secure_transport = ON
# 数据加密
innodb_encrypt_tables = ON
innodb_encrypt_log = ON
innodb_crypto_algorithm = AES_256_GCM
# 连接控制
max_connections = 500
max_connect_errors = 100
wait_timeout = 3600
interactive_timeout = 3600
# 二进制日志
log_bin = /var/log/mysql/binlog
binlog_format = ROW
expire_logs_days = 7操作最佳实践
推荐操作:
日常操作安全:
- 使用专用管理工具
- 避免在命令行中使用明文密码
- 启用会话超时
- 记录管理操作
安全操作示例:
bash
# 使用 mysql_config_editor 存储密码
mysql_config_editor set --login-path=client --host=localhost --user=admin --password
# 使用登录路径连接
mysql --login-path=client
# 启用会话超时
mysql --connect-timeout=30 --wait-timeout=3600监控最佳实践
推荐监控:
安全监控:
- 监控异常连接
- 监控权限变更
- 监控敏感操作
- 监控登录失败
监控工具:
- MySQL Enterprise Monitor
- Percona Monitoring and Management
- Prometheus + Grafana
- 自定义监控脚本
监控示例:
sql
-- 监控登录失败
SELECT * FROM performance_schema.host_cache
WHERE SUM_CONNECT_ERRORS > 0;
-- 监控权限变更
SELECT * FROM mysql.general_log
WHERE command_type = 'GRANT' OR command_type = 'REVOKE';
-- 监控异常连接
SELECT * FROM information_schema.processlist
WHERE time > 600;常见问题(FAQ)
Q1:如何保护 MySQL 根用户密码?
A1:
- 使用
mysql_config_editor存储密码 - 避免在脚本中硬编码密码
- 定期更改根密码
- 限制根用户只能从本地访问
Q2:如何检测 MySQL 安全漏洞?
A2:
- 使用专业漏洞扫描工具
- 定期检查 MySQL 版本
- 关注 MySQL 安全公告
- 扫描系统漏洞
Q3:如何防止 SQL 注入攻击?
A3:
- 使用参数化查询
- 实施输入验证
- 使用最小权限原则
- 启用 MySQL 查询重写
Q4:如何保护敏感数据?
A4:
- 使用表空间加密
- 在应用层加密敏感数据
- 实施访问控制
- 审计敏感数据访问
Q5:如何应对 MySQL 安全事件?
A5:
- 执行应急响应计划
- 隔离受影响的系统
- 保存事件证据
- 恢复系统从备份
- 分析事件原因并改进
Q6:如何确保 MySQL 备份安全?
A6:
- 加密备份文件
- 限制备份文件访问权限
- 存储备份在安全位置
- 定期测试备份恢复
- 实施备份轮换策略
