mysql_secure_installation 可完成大部分,但理解每項含義更利於合規審計。# 命令列
mysqladmin -u root password 'StrongP@ssw0rd!2024'
# 或 SQL
ALTER USER 'root'@'localhost' IDENTIFIED BY 'StrongP@ssw0rd!2024';
FLUSH PRIVILEGES;
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\_%';
DELETE FROM mysql.user WHERE User='';
FLUSH PRIVILEGES;
-- 方案 A:改名(推薦)
RENAME USER 'root'@'localhost' TO 'dba_admin'@'localhost';
-- 方案 B:僅允許本地
DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost','127.0.0.1','::1');
FLUSH PRIVILEGES;
CREATE DATABASE app_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'app_user'@'10.0.%' IDENTIFIED BY 'AppUserStr0ngP@ss!';
GRANT SELECT, INSERT, UPDATE, DELETE, EXECUTE ON app_db.* TO 'app_user'@'10.0.%';
-- 嚴禁 GRANT ALL、FILE、SUPER、SHUTDOWN、PROCESS 等管理權限
FLUSH PRIVILEGES;
[mysqld]
local_infile = 0
secure_file_priv = /var/lib/mysql-files/ # 僅允許此目錄 LOAD DATA/SELECT INTO OUTFILE
動態生效需重啟;驗證:SHOW VARIABLES LIKE 'local_infile'; 應為 OFF。
[mysqld]
# 完全禁用 TCP/IP(僅本地 Unix Socket)
skip-networking
# 或綁定內網 IP
bind-address = 10.0.0.10
# 生產建議:bind-address=0.0.0.0 + 防火牆/安全組限制來源 IP
ALTER USER 'app_user'@'10.0.%'
WITH MAX_QUERIES_PER_HOUR 10000
MAX_UPDATES_PER_HOUR 5000
MAX_CONNECTIONS_PER_HOUR 2000
MAX_USER_CONNECTIONS 50;
# MariaDB / Percona / MySQL Enterprise
INSTALL PLUGIN audit_log SONAME 'audit_log.so';
SET GLOBAL audit_log_policy = 'ALL';
SET GLOBAL audit_log_format = 'JSON';
[mysqld]
ssl_ca = /etc/mysql/ssl/ca.pem
ssl_cert = /etc/mysql/ssl/server-cert.pem
ssl_key = /etc/mysql/ssl/server-key.pem
require_secure_transport = ON
# 客戶端連接
mysql --ssl-mode=VERIFY_IDENTITY -h db-host -u user -p
# 全庫檢查並修復
mysqlcheck -A --auto-repair -u root -p
# 單庫優化(重建索引、碎片整理)
mysqlcheck -o -r app_db -u root -p
| 模板 | 適用記憶體 | 核心參數特徵 |
|---|---|---|
| my-small.cnf | < 64 MB | 極小緩衝,嵌入式/測試 |
| my-medium.cnf | 64-128 MB | key_buffer=16M, sort_buffer=1M |
| my-large.cnf | 512 MB | innodb_buffer_pool=128M |
| my-huge.cnf | 1-2 GB | innodb_buffer_pool=512M |
| my-innodb-heavy-4G.cnf | 4 GB+ | innodb_buffer_pool=2G+, log_file=256M |
生產環境請根據實際記憶體 **自行計算** innodb_buffer_pool_size = 物理記憶體 × 60-75%,而非直接套用模板。
<?php
// audit_mysql_security.php
$pdo = new PDO('mysql:host=localhost', 'dba_admin', 'pwd');
$checks = [
"SELECT User, Host FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost','127.0.0.1','::1')" => "Root 遠程登入",
"SELECT User, Host FROM mysql.user WHERE User=''" => "匿名用戶",
"SHOW VARIABLES LIKE 'local_infile'" => "LOCAL INFILE 應為 OFF",
"SHOW VARIABLES LIKE 'secure_file_priv'" => "secure_file_priv 應非空",
"SELECT User, Host, MAX_USER_CONNECTIONS FROM mysql.user WHERE MAX_USER_CONNECTIONS = 0" => "無連接數限制用戶",
];
foreach ($checks as $sql => $desc) {
$stmt = $pdo->query($sql);
if ($stmt->rowCount() > 0) {
echo "[FAIL] $desc\n";
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $r) print_r($r);
} else {
echo "[OK] $desc\n";
}
}
安全配置不是一次性動作,而是**持續流程**:安裝即加固 → 定期審計 → 版本升級同步修正 → 事件響應預案。將上述 9 項納入基線檢查清單,自動化巡檢,才能守住資料資產底線。