MySQL 開啟遠程存取:建立遠程用戶、防火牆與 bind-address 完整配置
預設 MySQL 僅監聽 127.0.0.1,遠程連線會被拒絕。本文涵蓋用戶建立、網路配置、防火牆、SSL 加密與驗證步驟,確保遠程存取安全合規。
步驟 1:建立遠程用戶(推薦 8.0+ 語法)
-- 登入本機 root
mysql -u root -p
-- 建立用戶允許任意 IP 連線(生產請限制具體 IP/網段)
CREATE USER 'remote_user'@'%' IDENTIFIED BY 'StrongPassw0rd!';
-- 授權特定資料庫
GRANT SELECT, INSERT, UPDATE, DELETE ON `mydb`.* TO 'remote_user'@'%';
-- 刷新權限
FLUSH PRIVILEGES;
步驟 2:修改 bind-address 監聽所有介面
# 編輯配置檔
vi /etc/my.cnf # 或 /etc/mysql/my.cnf /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
# 註釋或修改預設 127.0.0.1
bind-address = 0.0.0.0
# 或具體 IP:bind-address = 192.168.1.100
# 重啟生效
systemctl restart mysqld
步驟 3:防火牆放行 3306 埠
# firewalld (CentOS 7+/RHEL 7+)
firewall-cmd --permanent --add-port=3306/tcp
firewall-cmd --reload
# iptables
iptables -A INPUT -p tcp --dport 3306 -j ACCEPT
service iptables save
# ufw (Ubuntu)
ufw allow 3306/tcp
# 雲廠商安全組:同樣需在控制台放行 3306 入站規則,來源建議限定應用伺服器 IP
步驟 4:驗證遠程連線
# 遠程客戶端測試
mysql -u remote_user -p -h 192.168.1.100 -P 3306
# 或指定協定
mysql -u remote_user -p -h 192.168.1.100 --protocol=TCP
# 檢查監聽
ss -tlnp | grep 3306
# 輸出應包含 0.0.0.0:3306 或 ::1:3306
步驟 5:安全加固(生產環境必做)
| 措施 | 配置方式 |
| 限制來源 IP | 用戶 'user'@'192.168.1.%'、安全組/防火牆白名單 |
| 強制 SSL 傳輸 | ALTER USER 'remote_user'@'%' REQUIRE SSL;,客戶端 --ssl-mode=REQUIRED |
| 修改預設埠 | port = 33067 避免自動掃描 |
| 禁用 root 遠程登入 | 確保無 'root'@'%',DROP USER 'root'@'%'; |
| 啟用審計日誌 | MariaDB Audit Plugin / MySQL Enterprise Audit |
| 連線數限制 | GRANT ... WITH MAX_CONNECTIONS_PER_HOUR 1000 |
常見連線失敗排查
| 錯誤 | 原因 | 解決 |
| Can't connect to MySQL server (111/113) | 網路不通/防火牆/bind-address | telnet IP 3306、檢查防火牆、確認 bind-address=0.0.0.0 |
| Access denied for user 'x'@'ip' | 用戶 Host 不匹配/密碼錯 | 檢查 SELECT User, Host FROM mysql.user、重設密碼 |
| Host 'x.x.x.x' is not allowed to connect | 無對應 Host 用戶 | 建立 'user'@'x.x.x.x' 或 'user'@'%' |
| SSL connection error | 客戶端/伺服器 SSL 協定不匹配 | 客戶端 --ssl-mode=PREFERRED 或同步憑證 |
連線字串範例
# JDBC
jdbc:mysql://192.168.1.100:3306/mydb?useSSL=true&verifyServerCertificate=false&requireSSL=true
# Python (mysql-connector-python)
cnx = mysql.connector.connect(
host="192.168.1.100", port=3306,
user="remote_user", password="StrongPassw0rd!",
database="mydb", ssl_ca="/path/to/ca.pem", ssl_verify_cert=True
)
# Go (go-sql-driver/mysql)
db, _ := sql.Open("mysql", "remote_user:StrongPassw0rd!@tcp(192.168.1.100:3306)/mydb?tls=custom")