核心命令:授權遠程訪問
-- 1. 登錄 MySQL
mysql -uroot -p
-- 2. 創建遠程訪問用戶 (推薦:專用用戶、指定 IP 段、最小權限)
CREATE USER 'app_user'@'192.168.1.%' IDENTIFIED BY 'StrongPass123!';
-- 3. 授權最小必要權限 (僅業務庫、僅增刪改查)
GRANT SELECT, INSERT, UPDATE, DELETE, EXECUTE ON `biz_db`.* TO 'app_user'@'192.168.1.%';
-- 4. 刷新權限生效
FLUSH PRIVILEGES;
配置文件綁定地址 (關鍵步驟)
[mysqld]
# 監聽所有網卡 (允許遠程連接)
bind-address = 0.0.0.0
# 或指定具體內網 IP
# bind-address = 192.168.1.100
# 禁用本地回環のみ (僅允許本機)
# bind-address = 127.0.0.1 # 默認值,拒絕遠程
# 跳過 DNS 反向解析 (提速、避免解析失敗導致連接慢)
skip-name-resolve = ON
修改後 **必須重啟 MySQL**:systemctl restart mysqld
防火牆放行端口
| 系統 | 命令 |
| CentOS 7+ / RHEL 7+ (firewalld) | firewall-cmd --permanent --add-port=3306/tcp --zone=internal
firewall-cmd --reload |
| Ubuntu 18.04+ (ufw) | ufw allow from 192.168.1.0/24 to any port 3306 proto tcp |
| 通用 iptables | iptables -A INPUT -s 192.168.1.0/24 -p tcp --dport 3306 -j ACCEPT
service iptables save |
| 云服务器安全组 | 控制台添加入站規則:來源 192.168.1.0/24、協議 TCP、端口 3306 |
驗證連通性
# 客戶端機器執行
# 1. TCP 端口探測
telnet 192.168.1.100 3306
# 或
nc -zv 192.168.1.100 3306
# 2. MySQL 客戶端連接
mysql -h 192.168.1.100 -u app_user -p'StrongPass123!' -D biz_db -e "SELECT VERSION();"
# 3. 應用驗證 (JDBC URL 示例)
jdbc:mysql://192.168.1.100:3306/biz_db?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8mb4
安全加固清單 (生產環境必做)
| 措施 | 實施方式 | 風險降低 |
| 禁用 root 遠程登錄 | DELETE FROM mysql.user WHERE User='root' AND Host!='localhost'; FLUSH PRIVILEGES; | 防止暴力破解最高權限賬號 |
| 匿名用戶清理 | DELETE FROM mysql.user WHERE User=''; FLUSH PRIVILEGES; | 消除無密碼登錄風險 |
| 刪除 test 數據庫 | DROP DATABASE test; DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%'; FLUSH PRIVILEGES; | 減少攻擊面 |
| 強密碼策略 | 安裝 validate_password 組件,設置 MEDIUM/STRONG 級別 | 防止弱密碼被撞庫 |
| SSL/TLS 加密傳輸 | 生成證書,配置 require_secure_transport=ON,用戶 REQUIRE SSL | 防止局域網抓包竊取數據/密碼 |
| 限制連接數 | GRANT ... WITH MAX_CONNECTIONS_PER_HOUR 1000 MAX_USER_CONNECTIONS 50 | 防止單用戶佔用所有連接 |
| 審計日志 | 安裝 Audit 插件,記錄登錄、DDL、DML、失敗嘗試 | 事後追溯、合規 |
| 非標準端口 | 修改 port=33060,安全組同步修改 | 降低自動掃描腳本命中率 |
| 定期輪換密鑰 | 腳本自動化:ALTER USER ... IDENTIFIED BY ... + 應用配置熱更新 | 縮短洩露窗口期 |
常見連接失敗排查
| 現象 | 可能原因 | 排查命令 |
| ERROR 2003 (Can't connect) | 服務未啟動、bind-address 錯誤、防火牆阻攔、安全組未放行、IP 不在授權段 | systemctl status mysqld、ss -ntlp | grep 3306、telnet IP 3306、SELECT User,Host FROM mysql.user; |
| ERROR 1045 (Access denied) | 用戶名/密碼錯誤、Host 不匹配 (如用戶@192.168.1.% 但客戶端 IP 10.0.0.1)、密碼插件不匹配 (caching_sha2_password vs mysql_native_password) | SELECT User,Host,plugin FROM mysql.user WHERE User='app_user';、客戶端指定 --default-auth=mysql_native_password |
| ERROR 1130 (Host not allowed) | 用戶 Host 列不匹配客戶端 IP | RENAME USER 'app_user'@'old_ip' TO 'app_user'@'new_ip%'; 或 CREATE USER 'app_user'@'%' ... (慎用) |
| 連接極慢 (數秒) | DNS 反向解析超時 | 配置 skip-name-resolve=ON,或 /etc/hosts 添加客戶端 IP 映射 |
| SSL 握手失敗 | 客戶端不支持 TLS 版本、證書過期、CA 不信任 | SHOW VARIABLES LIKE 'tls_version';、客戶端 useSSL=true&verifyServerCertificate=false |
自動化部署腳本片段 (Ansible 任務)
- name: Configure MySQL remote access
hosts: db_servers
become: yes
vars:
mysql_bind_address: "0.0.0.0"
mysql_remote_user: "app_user"
mysql_remote_host: "192.168.1.%"
mysql_remote_pass: "{{ vault_mysql_app_pass }}"
mysql_remote_db: "biz_db"
tasks:
- name: Set bind-address in my.cnf
lineinfile:
path: /etc/my.cnf
regexp: '^bind-address'
line: "bind-address = {{ mysql_bind_address }}"
notify: restart mysqld
- name: Ensure skip-name-resolve
lineinfile:
path: /etc/my.cnf
regexp: '^skip-name-resolve'
line: "skip-name-resolve = ON"
notify: restart mysqld
- name: Create remote user and grant privileges
mysql_user:
name: "{{ mysql_remote_user }}"
host: "{{ mysql_remote_host }}"
password: "{{ mysql_remote_pass }}"
priv: "{{ mysql_remote_db }}.*:SELECT,INSERT,UPDATE,DELETE,EXECUTE"
state: present
notify: flush privileges
handlers:
- name: restart mysqld
systemd:
name: mysqld
state: restarted
- name: flush privileges
command: mysql -uroot -p"{{ vault_mysql_root_pass }}" -e "FLUSH PRIVILEGES;"
總結
開放 MySQL 遠程連接**不是簡單的 GRANT ALL ON *.* TO root@'%'**,而是遵循**最小權限、網絡隔離、加密傳輸、審計記錄、自動化管理**的系統工程。核心三步:bind-address=0.0.0.0 + CREATE USER ...@'具體IP段' + GRANT 最小權限 ON 業務庫.*,配合防火牆、SSL、密碼策略、審計插件,構建纵深防御體系。