原创

MySQL从入门到生产(四):安全加固

温馨提示:
本文最后更新于 2025年07月12日,已超过 208 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

 

一、引言

在当今数据驱动的商业环境中,数据库作为企业核心数据载体,其安全性直接关系到信息资产的保密性、完整性和可用性。根据近年来的数据泄露事件分析,超过68%的企业因数据库基础安全配置不足而遭受数据泄露 。MySQL 8.0 作为全球最流行的开源数据库管理系统,提供了一系列强大的安全增强功能,能够帮助企业构建纵深防御体系,满足等保2.0、GDPR等合规要求 。

本文将系统介绍MySQL 8.0的安全整改实践,从传输加密、访问控制、审计日志等多个维度,为企业提供一套完整的安全加固方案。无论您是数据库管理员、安全工程师还是系统架构师,都能从中获得实用的配置指导和技术洞察。

二、传输加密:杜绝明文通信

1.风险分析

账号、密码、业务数据通过明文传输,易被网络嗅探或中间人攻击(MITM)截获,造成凭证泄露与非授权访问。

2.整改目标

强制所有客户端连接使用 SSL/TLS 加密,禁用非安全通道。

3.实施步骤

生成 SSL 证书(以 mysql 用户身份)

cd /opt/mysql/data/
sudo -u mysql mysql_ssl_rsa_setup --datadir=/opt/mysql/data/

私钥必须严格保护

sudo chmod 600 server-key.pem
sudo chmod 644 *.pem
sudo chown mysql:mysql *.pem

配置 my.cnf

[mysqld]
require_secure_transport = ON
ssl-ca    = ca.pem
ssl-cert  = server-cert.pem
ssl-key   = server-key.pem
tls_version = TLSv1.2,TLSv1.3  # 禁用弱协议

Java 应用连接(推荐 PEM 直接引用)

JDBC 8.0.22+ 支持直接读取 PEM 文件,无需 keytool 转换:

jdbc:mysql://db-host:3306/mydb?
  useSSL=true&
  requireSSL=true&
  verifyServerCertificate=true&
  sslMode=VERIFY_CA&
  trustCertificateKeyStoreUrl=file:/opt/mysql/data/ca.pem&
  trustCertificateKeyStoreType=PEM

若必须使用 JKS,再执行:

keytool -importcert -alias mysql-ca -file ca.pem -keystore truststore -storepass YourStrongPass

验证

SELECT @@have_ssl, @@have_openssl;          -- 应为 YES
SELECT @@require_secure_transport;          -- 应为 1
SHOW STATUS LIKE 'Ssl_cipher';              -- 非空表示当前连接已加密

三、安全审计:实现行为可追溯

1.危害分析

缺乏审计能力会导致安全事件无法追溯,难以发现潜在威胁和违规操作。特别是在等保合规要求下,审计日志是满足合规性的必要条件 。

2.整改建议

开启完整的审计日志功能,覆盖所有用户行为和安全事件。MySQL 8.0提供了强大的审计插件,可记录所有数据库操作。

3.实施方案

1. 安装审计插件

-- 安装审计插件
INSTALL PLUGIN audit_log SONAME 'audit_log.so';

-- 验证插件状态
SHOW PLUGINS;

2. 配置审计日志

在my.cnf配置文件中添加:

[mysqld]
# 基础日志配置
general_log = 1
general_log_file = /opt/mysql/logs/query.log
log_error = /opt/mysql/logs/error.log
log_bin = /opt/mysql/logs/binlog

# 审计插件配置
plugin-load-add = audit_log.so
audit_log_format = JSON
audit_log_file = /opt/mysql/logs/audit.log
audit_log_policy = ALL
audit_log_rotate_on_size = 100000000
audit_log_flush = ON

3. 审计日志管理

-- 查看审计相关配置
SHOW VARIABLES LIKE 'audit_log%';

-- 手动轮转审计日志
ALTER INSTANCE ROTATE AUDIT LOG;

审计内容分析

审计日志通常包含以下关键信息 :

  • 用户身份和来源IP
  • 操作类型(查询、更新、删除等)
  • 执行时间和时间戳
  • 受影响的对象和数据库
  • 操作结果(成功或失败)

验证方法

SHOW VARIABLES LIKE 'log_error';     -- 错误日志路径
SHOW VARIABLES LIKE 'general_log';   -- 应为ON
SHOW VARIABLES LIKE 'log_bin';       -- 应为ON

-- 检查审计日志是否正常记录
tail -f /opt/mysql/logs/audit.log

四、身份认证安全:强化密码策略

1.危害分析

弱密码和空密码容易被暴力破解,成为安全体系的薄弱环节。据统计,弱密码是导致数据库未授权访问的主要原因之一 。

2.整改建议

实施强密码策略,确保密码复杂度和定期更换。MySQL 8.0提供了密码验证插件,可强制实施密码策略。

3.实施方案

1. 安装密码验证插件

INSTALL PLUGIN validate_password SONAME 'validate_password.so';

2. 配置密码策略

[mysqld]
# 密码验证插件配置
plugin-load-add = validate_password.so
validate_password_policy = MEDIUM
validate_password_length = 12
validate_password_mixed_case_count = 1
validate_password_number_count = 1
validate_password_special_char_count = 1
validate_password_check_user_name = ON

# 密码有效期配置
default_password_lifetime = 90
password_reuse_interval = 365
password_require_current = ON

3. 密码策略参数说明

  • validate_password_policy:密码策略等级(LOW=0, MEDIUM=1, STRONG=2)
  • validate_password_length:密码最小长度
  • validate_password_mixed_case_count:大小写字母最少数量
  • validate_password_number_count:数字最少数量
  • validate_password_special_char_count:特殊字符最少数量

验证方法

-- 查看密码策略配置
SHOW VARIABLES LIKE 'validate_password%';

-- 检查用户密码状态
SELECT user, host, password_lifetime, password_last_changed 
FROM mysql.user;

-- 检查空密码账户
SELECT user, host FROM mysql.user WHERE authentication_string = '';

五、静态数据加密:守护存储层安全

1.风险分析

.ibd 表空间文件、binlog、备份若未加密,一旦磁盘被盗或云存储泄露,数据将完全暴露。

2.整改目标

启用 InnoDB 表空间加密 + 二进制日志加密。

3.配置

[mysqld]
# 加载密钥环插件
early-plugin-load = keyring_file.so
keyring_file_data = /opt/mysql/keyring/.keyring

# 启用表空间加密(需 innodb_file_per_table=1)
innodb_file_per_table = 1

# 启用 binlog 加密(MySQL 8.0.14+)
binlog_encryption = ON

创建加密表

CREATE TABLE user_info (
    id INT PRIMARY KEY,
    ssn VARCHAR(20)
) ENCRYPTION = 'Y';

验证

-- 检查加密表
SELECT TABLE_SCHEMA, TABLE_NAME 
FROM INFORMATION_SCHEMA.TABLES 
WHERE CREATE_OPTIONS LIKE '%ENCRYPTION="Y"%';

-- 检查 binlog 是否加密
SHOW VARIABLES LIKE 'binlog_encryption'; -- ON

注意:密钥文件 /opt/mysql/keyring/.keyring 必须严格保护(权限 600,属主 mysql)。

六、权限控制:践行最小权限原则

1.风险分析

过度授权(如 GRANT ALLSUPER 权限)使普通用户具备管理员能力,极易被利用。

2.整改目标

按需授权,定期审计,回收冗余权限。

3.最佳实践

1. 创建专用应用账户

CREATE USER 'app_user'@'192.168.1.%' 
  IDENTIFIED WITH caching_sha2_password BY 'Str0ngP@ss!2026';

GRANT SELECT, INSERT, UPDATE, DELETE ON app_db.* TO 'app_user'@'192.168.1.%';

2. 回收危险权限

-- 禁止非 DBA 用户拥有 FILE、SUPER 等权限
REVOKE FILE, PROCESS, SUPER, SHUTDOWN, RELOAD ON *.* FROM 'dev_user'@'%';

3. 定期审计

-- 查找拥有 SUPER 权限的用户
SELECT user, host FROM mysql.user WHERE super_priv = 'Y';

-- 检查全局权限
SELECT user, host, Select_priv, Insert_priv, Grant_priv FROM mysql.user;

七、访问控制:缩小攻击面

1.风险分析

默认 bind-address = * 允许任意 IP 连接,极大增加暴露风险。

2.整改目标

限制监听地址 + 防火墙双重防护。

3.配置

1. MySQL 绑定地址

[mysqld]
bind-address = 127.0.0.1        # 仅本地访问
# 或 bind-address = 192.168.1.100  # 指定内网IP

2. 防火墙规则(UFW 示例)

sudo ufw allow from 192.168.1.0/24 to any port 3306
sudo ufw deny 3306  # 默认拒绝

验证

SHOW VARIABLES LIKE 'bind_address';

严禁将 3306 端口暴露至公网!

八、服务安全:非特权运行

1.风险分析

root 运行 MySQL,一旦被攻破,攻击者将获得系统最高权限。

2.整改目标

使用专用低权限账户运行服务。

3.配置

1. 创建专用用户(若未存在)

sudo groupadd mysql
sudo useradd -r -g mysql -s /bin/false mysql

2. 设置目录权限

sudo chown -R mysql:mysql /opt/mysql/data /opt/mysql/logs /opt/mysql/keyring
sudo chmod 750 /opt/mysql/data

3. 配置 systemd 服务

编辑 /etc/systemd/system/mysqld.service

[Service]
User=mysql
Group=mysql

验证

ps -ef | grep mysqld | grep -v grep
# 输出应为:mysql ... /usr/sbin/mysqld ...
正文到此结束