诡异bug:数据库进程无法启动?自环连接是什么鬼

Linux上一个客户端程序不断的尝试连接数据库。如果数据库需要停一下,比如:升级。结果发现启动报错,启动不起来了。

看启动命令的报错,信息很少。开始看mysql的/var/log/db/error.log,发现时间不对,以为是历史日志。感谢曹大帮忙,确认错误日志是启动时产生的,可能是时区设置导致时间不对。进而判断出是端口被占用导致的。

但没有进程回占用数据库进程的监听端口啊?经排查发现了下面的这个奇葩连接。

# netstat -na | grep xxxx

tcp 0 0 127.0.0.1:XXXX127.0.0.1:XXXXESTABLISHED

细想一下,这个自环连接怎么建立起来的哪?源IP:端口等于目的IP:端口。没有人监听在这个端口,竟然因为源端口是这个端口,就连上了?谁发的sys/ack报文?

经确认,还真是这样。在Linux上,不断的尝试连接一个没有开的端口,比如1234,经过几千次尝试,如果碰巧源端口也是1234,就建立了连接。

比如运行下面的脚本:

while true

do

telnet 127.0.0.1 1234

done

尝试一会儿就会显示,连上了。你可以自己和自己聊天了。

Trying 127.0.0.1...

telnet: Unable to connect to remote host: Connection refused

Trying 127.0.0.1...

telnet: Unable to connect to remote host: Connection refused

Trying 127.0.0.1...

Connected to 127.0.0.1.

Escape character is '^]'.

# netstat -na | grep 1234

tcp 0 0 127.0.0.1:1234127.0.0.1:1234ESTABLISHED

Mac上据说做了源/目的端口一致的判断,避免了这种问题。

规避方法之一是修改本地随机端口的选择范围。缺省是1024,改到更高的端口,避开你常用的端口。

# cat /proc/sys/net/ipv4/ip_local_port_range

# echo “1235 65000" > /proc/sys/net/ipv4/ip_local_port_range

另一种方法,设置socket的读超时。虽然连接能很诡异的建立起来,但这个socket是读不出来数据的。读取超时后,断开连接即可。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180801G1LNZ500?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券