前言

最近開發中遇到一個問題,mysql在伺服器本地可以登入,但是遠端通過3306埠卻不可以。這個問題困擾了我一週之久,終於在今天解決了。在解決的過程中試了很多的方法,遂記錄下來,希望能給大家一些提示。

排查錯誤位置

客戶端方面

首先通過ping命令對伺服器進行測試,如果ping不通,則是網路的問題,本文中沒有涉及這類問題的解決。

如果能ping通,再測試埠有沒有問題。首先安裝telnet, telnet是windows系統自帶的,搜尋"啟動或關閉Windows功能", 找telnet客戶端,勾選即可啟動。在cmd中輸入telnet {伺服器IP} 3306, 如果不能正確連線,說明是埠設定的問題, 再試試22埠有沒有問題,如果也有問題,就是伺服器整體的埠設定有問題,如果只有3306有問題,那麼就是3306埠、mysql的設定問題,繼續往下測試。

伺服器方面

針對只有3306埠不能連線的情況,有以下幾種解決方法:

1. 修改配置檔案,開啟對其他ip地址的監聽

輸入命令netstat -ntpl |grep 3306netstat -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埠成功了。(忽略這裡的亂碼)