深色模式
数据库安全加固
摘要:数据库安全做四件事:传输加密(TLS)、存储加密(TDE/表空间加密)、敏感数据脱敏、账号权限回收与审计。本文给出 MySQL 上的可操作配置与验证命令。
适用环境
bash
mysql -uroot -p -e "SHOW VARIABLES LIKE 'have_ssl'; SHOW VARIABLES LIKE 'require_secure_transport';"
mysql -uroot -p -e "SELECT user, host, plugin FROM mysql.user;"1
2
2
操作步骤
1. 传输加密:开启 TLS
sql
-- 确认支持 SSL 并强制所有连接使用加密
SHOW VARIABLES LIKE 'have_ssl';
SET GLOBAL require_secure_transport = ON;1
2
3
2
3
ini
# /etc/my.cnf
require_secure_transport = ON
ssl_cert = /data/mysql/cert/server-cert.pem
ssl_key = /data/mysql/cert/server-key.pem1
2
3
4
2
3
4
bash
mysql --ssl-mode=REQUIRED -uroot -p -e "\s" | grep -i 'SSL'1
2. 强制账号使用加密连接
sql
ALTER USER 'app_rw'@'10.0.1.%' REQUIRE SSL;
ALTER USER 'app_rw'@'10.0.1.%' REQUIRE X509; -- 更严格:校验客户端证书1
2
2
3. 静态加密:InnoDB 表空间加密
sql
INSTALL PLUGIN keyring_file SONAME 'keyring_file.so';
SET GLOBAL keyring_file_data = '/data/mysql/keyring/keyring';1
2
2
ini
# 持久化并开启默认表加密
early-plugin-load=keyring_file.so
keyring_file_data=/data/mysql/keyring/keyring
default_table_encryption=ON
innodb_redo_log_encrypt=ON1
2
3
4
5
2
3
4
5
sql
-- 对已有表启用加密
ALTER TABLE shopdb.user_profile ENCRYPTION='Y';
SELECT table_name, create_options FROM information_schema.tables
WHERE create_options LIKE '%ENCRYPTION%';1
2
3
4
2
3
4
危险
密钥文件(keyring)一旦丢失,加密数据将永久无法读取。必须与数据分开备份、异地保存,并测试过恢复流程。
4. 敏感数据脱敏
sql
-- 查询时脱敏:手机号中间四位打星
SELECT CONCAT(LEFT(phone,3), '****', RIGHT(phone,4)) AS phone_mask FROM users LIMIT 5;
-- 用视图对不具备权限的账号提供脱敏数据
CREATE VIEW v_users AS
SELECT id, CONCAT(LEFT(phone,3),'****',RIGHT(phone,4)) AS phone FROM users;
GRANT SELECT ON shopdb.v_users TO 'app_ro'@'10.0.1.%';1
2
3
4
5
6
7
2
3
4
5
6
7
sql
-- 导出给测试环境前先做静态脱敏
-- mysqldump ... | sed 处理,或在导出脚本中直接 UPDATE 脱敏字段1
2
2
5. 账号与权限加固
sql
-- 清理无密码与匿名账号
SELECT user, host FROM mysql.user WHERE authentication_string='' OR user='';
DROP USER IF EXISTS ''@'localhost';
-- 密码策略
SET GLOBAL validate_password.policy = STRONG; -- 需安装 validate_password 组件
ALTER USER 'app_ro'@'10.0.1.%' PASSWORD EXPIRE INTERVAL 90 DAY;
-- 回收不必要的全局权限
REVOKE ALL PRIVILEGES ON *.* FROM 'app_rw'@'10.0.1.%';
GRANT SELECT, INSERT, UPDATE, DELETE ON shopdb.* TO 'app_rw'@'10.0.1.%';1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
6. 网络与主机层
bash
# 禁止公网监听,仅内网地址
sudo ss -lntp | grep 3306
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.1.0/24" port protocol="tcp" port="3306" accept'
sudo firewall-cmd --reload1
2
3
4
2
3
4
验证
bash
mysql --ssl-mode=REQUIRED -uroot -p -e "SHOW STATUS LIKE 'Ssl_cipher';" # 非空即已加密
mysql --ssl-mode=DISABLED -uroot -p -e "SELECT 1"; # 应被拒绝1
2
2
- [ ] 无匿名/空密码账号,业务账号仅有库级必要权限
- [ ] 敏感字段在对外查询与导出中已脱敏
- [ ] 数据库端口不对公网开放
常见坑
WARNING
开启 TLS 会有一定 CPU 与握手开销;内网高 QPS 场景需评估,或只对跨机房链路强制加密。
WARNING
脱敏只是展示层的保护,若导出的是脱敏数据,测试环境的功能校验可能失效(如校验手机号格式),需与测试同学对齐。
DANGER
只做加密不控权限等于白做:拿到业务账号的人仍能看到明文。加密与最小权限必须同时落地。