前言
最近開發中遇到一個問題,mysql在伺服器本地可以登入,但是遠端通過3306埠卻不可以。這個問題困擾了我一週之久,終於在今天解決了。在解決的過程中試了很多的方法,遂記錄下來,希望能給大家一些提示。
排查錯誤位置
客戶端方面
首先通過ping命令對伺服器進行測試,如果ping不通,則是網路的問題,本文中沒有涉及這類問題的解決。
如果能ping通,再測試埠有沒有問題。首先安裝telnet, telnet是windows系統自帶的,搜尋"啟動或關閉Windows功能", 找telnet客戶端,勾選即可啟動。在cmd中輸入telnet {伺服器IP} 3306
, 如果不能正確連線,說明是埠設定的問題, 再試試22埠有沒有問題,如果也有問題,就是伺服器整體的埠設定有問題,如果只有3306有問題,那麼就是3306埠、mysql的設定問題,繼續往下測試。
伺服器方面
針對只有3306埠不能連線的情況,有以下幾種解決方法:
1. 修改配置檔案,開啟對其他ip地址的監聽
輸入命令netstat -ntpl |grep 3306
和 netstat -ntpl |grep 22
, 檢視埠的繫結情況
正確情況下應為以下輸出:
如果3306只繫結的本地埠,就會出現和上圖不一致的輸出。需要對其配置檔案進行修改:
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
開啟配置檔案, 找到bind-address開頭的一行,如果後面的ip地址是127.0.0.1,也就是伺服器只會接收本地的連線請求,那麼就需要改變此地址來指向外部的IP地址。例如,可以改為:
lc-messages-dir = /usr/share/mysql
skip-external-locking
#
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address = 0.0.0.0
如果你的mysql版本是MySQL 8+,那麼mysqld.cnf中可能不會包含bind-address這一行,應該像下面所示方法進行新增:
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
log-error = /var/log/mysql/error.log
bind-address = 0.0.0.0
修改完成後,儲存並退出。重啟mysql服務sudo systemctl restart mysql
,使得配置檔案的修改得以生效。
接下來再次回到客戶端進行驗證,如果能夠telnet連線3306埠,說明配置成功,如果還是不能連線,進入下一步驟。
2. 關閉防火牆
Ubuntu預設的防火牆為ufw。防火牆的作用是管理網路規則,預設情況下開啟防火牆是更好的選擇, 但是這裡為了排除debug時的影響,就先關閉一下。
檢視防火牆狀態sudo ufw status
, 如果顯示active, 就執行sudo ufw disable
關閉。
3. 修改 iptables
iptables定義了網路訪問規則,它工作在核心中,是一個網路過濾器。
執行
sudo iptables -I INPUT -p tcp --dport 3306 -j ACCEPT
表示新增接收3306埠的規則。
-I INPUT將當前命令插入在filter鏈的第一位置。
-p tcp表示新增tcp協議的擴充套件。
--dport XX-XX:指定目標埠。
-j ACCEPT: 規定的動作,這裡為接收。
完成後,儲存修改的配置sudo iptables-save
。
然後再次在客戶端用telnet進行測試,得到結果:
說明連線3306埠成功了。(忽略這裡的亂碼)