MySQL 远程连接超时问题的解决

之前用 docker 安装 gitea 的时候遇到了 MySQL 无法连接(连接超时:SQLSTATE[HY000] [2002] Operation timed out)的问题。以至于我只能放弃 docker 方案,直接安装到了宿主机。

今天,我在本地虚拟机里用 docker 安装 nextcloud 又遇到了这个问题。怎么都解决不了,一气之下删掉了虚拟机。直接在 windows10 上安装相关应用。但是,windows10 下的 fast-cgi 没有很好的守护程序(对应 linux 下的 php-fpm)。

所以最终可以预料的结果就是,我还是得重建虚拟机,安装应用。当然,可以放弃 docker 方案。但有点不甘心。所以,我还是在尝试解决 mysql 远程连接超时问题。

根本原因很简单:iptables 配置。

防火墙 iptables 配置

// 查看 iptables 的配置
sudo iptables -L -n --line-number

// 部分结果如下
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           
2    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
3    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:22
4    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80
5    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:443
6    DROP       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:3306
7    ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0            icmptype 8

可以看到,3306 被禁用了。所以,我们需要删掉第六条。

sudo iptables -D INPUT 6
// 然后可以通过 sudo iptables -L -n --line-number 看一下结果。

接着,开放 3306 端口

iptables -I INPUT -p tcp --dport 3306 -j ACCEPT

到这里就可以尝试连接一下 MySQL,看看效果了。如果当初我也这么操作也许就不会把这个问题延续至今了。

一般来说,我们修改了配置都是需要重启对应的服务的。没错,我当初就重启了。事实上,这一次我也重启了。只不过这次发现还是连接不上而心灰意冷之余我又执行了一次 sudo iptables -L -n –line-number 命令,看了一下 iptables 的配置。发现配置变成了原来的样子。

查了一下资料,原来 iptables 的修改在重启之后会恢复。也就是我实际上改对了,只是重启服务之后没了……没了……没了……😡(为什么专业的事情要交给专业的人做,因为他们知道坑在哪)。

保存 iptables 的修改

Ubuntu下如何永久保存iptables规则 – Nicolas (sourismu.me)

关于 ubuntu 下 iptables 的保存,这个文章里介绍了两种。我当然是选择了比较方便的第二种。

// 安装 iptables-persistent,实际上这个包我系统里已经有了
sudo apt install iptables-persistent
// 保存配置
netfilter-persistent  save

iptables-persistent 是作为系统服务运行的,开机后会自动加载已经保存的配置。

除了防火墙之外,MySQL 远程连接还需要其他配置。这里顺便写一下。

MySQL 用户远程登录授权

How to Allow Remote Connections to MySQL Database Server | Linuxize

【已解决】Navicat或pycharm远程连不上MySQL数据库问题 – 知乎 (zhihu.com)

默认情况下,MySQL 是只能本地登录,也就是只能通过 localhost/127.0.0.1 登录。要想允许其他 ip 登录。需要配置相关权限。

mysql -u root –p
mysql> GRANT ALL ON *.* TO root@'%' IDENTIFIED BY 'user_password';
mysql> flush privileges;

然后,MySQL 的配置文件(可以通过 mysql –help | grep my.cnf 查看文件位置)也需要修改一下。

sudo vim /etc/my.cnf
// 在 [mysqld] 部分添加/修改:
bind-address  = 0.0.0.0
# skip-networking
// 然后重启 mysql
service mysql restart

总结

MySQL 远程连接问题卡了很久,原因无非就是:

  1. MySQL 用户远程授权配置
  2. MySQL 配置文件配置
  3. iptables 防火墙设置
  4. ufw(ubuntu)防火墙设置
  5. 云服务商后台防火墙配置

我文章里并没有介绍全,因为引用的文章里已经介绍得很全面了。

总之,这个让人吐血的问题总算解决了。我得找个时间重建虚拟机安装 nextcloud 了。