前言:MySQL 安全不止於「設置密碼」
默認安裝的 MySQL 面臨:傳輸明文、匿名帳號、root 遠程登錄、文件讀寫權限過大、DNS 欺騙、本地日誌洩露等風險。本文系統梳理 **傳輸層加密、認證授權、系統層隔離、權限最小化、編程最佳實踐** 五大維度加固措施,構建生產級 MySQL 安全基線。
一、傳輸層加密:防竊聽、防篡改、防重放
| 方案 | 原理 | 適用場景 | 配置要點 |
| SSL/TLS | MySQL 內建支持,啟用 require_secure_transport=ON | 所有生產環境,特別是跨網段/雲上部署 | 生成 CA/Server/Client 證書;my.cnf 配置 ssl_ca/cert/key;用戶創建時 REQUIRE SSL |
| SSH 隧道 | 本地端口轉發 ssh -L 3306:localhost:3306 user@db_host | 運維連接、跳板機、不想改動 MySQL 配置 | 僅監聽 127.0.0.1:3306;禁用密碼認證,強制密鑰 |
| VPN/私有網絡 | VPC、WireGuard、ZeroTier 等將 DB 隔離在私有網段 | 雲原生架構、多區域部署 | 安全組/防火牆僅放行應用服務器 IP 訪問 3306 |
| 壓縮協議 | MySQL 3.22+ 支持 protocol_compression,增加抓包分析難度 | 輔助手段,不可替代加密 | 客戶端啟用 MYSQL_OPT_COMPRESS |
二、認證與授權:零信任原則落地
2.1 強密碼策略與插件
-- 安裝密碼驗證插件 (MySQL 5.6+)
INSTALL PLUGIN validate_password SONAME 'validate_password.so';
-- 配置強度
SET GLOBAL validate_password.length = 16;
SET GLOBAL validate_password.mixed_case_count = 1;
SET GLOBAL validate_password.number_count = 1;
SET GLOBAL validate_password.special_char_count = 1;
SET GLOBAL validate_password.policy = 'STRONG';
2.2 清理默認不安全帳號
-- 刪除匿名用戶
DELETE FROM mysql.user WHERE User='';
-- 禁止 root 遠程登錄
DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost','127.0.0.1','::1');
-- 或
ALTER USER 'root'@'%' ACCOUNT LOCK;
-- 刪除 test 數據庫及其權限
DROP DATABASE test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
FLUSH PRIVILEGES;
2.3 最小權限帳號設計模板
| 角色 | 典型權限 | Host 限制 |
| Web 應用讀寫 | SELECT, INSERT, UPDATE, DELETE ON app_db.* | 應用服務器 IP/子網 |
| Web 應用只讀 | SELECT ON app_db.* | 應用服務器 IP/子網 |
| 備份帳號 | SELECT, LOCK TABLES, SHOW VIEW, EVENT, TRIGGER, RELOAD ON *.* | 備份服務器 IP |
| 監控帳號 | PROCESS, REPLICATION CLIENT, SELECT ON performance_schema.* | 監控系統 IP |
| ETL/數據分析 | SELECT, CREATE TEMPORARY TABLES ON dw_db.* | ETL 服務器 IP |
| DBA 管理 | ALL PRIVILEGES ON *.* WITH GRANT OPTION | 堡壘機/管理網段 + MFA |
三、系統層隔離:主機安全 = 數據庫安全
- 專用運行用戶:
useradd -r -s /sbin/nologin -d /var/lib/mysql mysql,嚴禁 root 運行 mysqld。
- 數據目錄權限 750:
chown -R mysql:mysql /var/lib/mysql && chmod 750 /var/lib/mysql,防止本地用戶讀取/拷貝 .ibd/.frm 文件繞過 SQL 權限。
- 配置文件權限 640:
chown root:mysql /etc/my.cnf && chmod 640 /etc/my.cnf,防止密碼洩露(早期版本可能在 my.cnf 寫密碼)。
- 禁用 LOCAL INFILE:
local_infile=OFF (客戶端/服務端雙向),防止 LOAD DATA LOCAL INFILE '/etc/passwd' INTO TABLE t 讀取服務器任意文件。
- 啟用審計日志:MariaDB/MySQL Enterprise Audit 或開源
McAfee Audit Plugin,記錄登錄、DDL、DML、錯誤、訪問敏感表。
四、權限最小化:危險權限「零授權」清單
| 權限 | 風險 | 策略 |
FILE | 讀寫服務器文件系統 (SELECT ... INTO OUTFILE, LOAD DATA INFILE) | 僅 DBA/備份帳號按需授予,且限制 secure_file_priv 目錄 |
PROCESS | 查看所有連接執行的 SQL (SHOW PROCESSLIST),可見敏感 SQL 含密碼 | 僅監控/管理帳號授予 |
SUPER | KILL 線程、修改全局變量、啟用日志、執行 CHANGE MASTER | 極度收緊,僅 DBA |
SHUTDOWN | 關閉服務器 | 禁用 |
CREATE USER, GRANT OPTION | 權限提升、橫向移動 | 僅 DBA |
RELOAD | FLUSH PRIVILEGES/LOGS/HOSTS,可影響複製、日志 | 備份/管理帳號按需 |
五、編程最佳實踐:從源頭杜絕注入與洩露
- 參數化查詢 (Prepared Statements):所有語言/框架統一使用,絕不拼接 SQL。
- 連接字符串指定字符集:
charset=utf8mb4,避免隱式轉換導致繞過/亂碼。
- 錯誤信息不回顯給前端:捕獲異常記錄日志,返回通用「系統繁忙」。
- 敏感字段應用層加密:密碼
Argon2id/Bcrypt,身份證/銀行卡 AES-GCM,密鑰由 KMS/Vault 管理,數據庫不存明文。
- 連接池配置:合理設置
max_pool_size、connection_timeout、idle_timeout,防止連接洩露耗盡數據庫連接數。
六、網絡與訪問控制
- 安全組/iptables/nftables:僅放行應用服務器 IP 訪問 3306,拒絕 0.0.0.0/0。
- 修改默認端口 (非安全核心,但可減少自動化掃描噪音)。
- 啟用
skip_name_resolve=ON,避免 DNS 解析延遲與欺騙,權限表直接使用 IP/CIDR。
- 生產環境 禁用公網 IP 直連,走 VPN/堡壘機/SSH 隧道。
七、備份與恢復演練:最後一道防線
- 邏輯備份:
mysqldump --single-transaction --routines --triggers --events --master-data=2
- 物理備份:
xtrabackup --parallel=4 --compress --target-dir=/backup
- 異地多副本:本地 + 異地雲存儲 (S3/OSS/COS) + 磁帶/冷存儲。
- 季度級恢復演練:驗證備份完整性、RTO/RPO 指標、應用兼容性。
結語
MySQL 安全是一個系統工程:**傳輸加密保機密性、最小權限限破壞面、系統隔離防繞過、審計日志可追溯、備份演練保可用性**。將上述清單納入基線巡檢、CI/CD 門禁、定期滲透測試,方能構建經得起實戰考驗的數據庫安全防線。