作者:Mr林_月生链接:https://www.jianshu.com/p/3ab10c8685b5
现象
直接上图
可以发现,本地没监听50000端口的服务,但是尝试连接本地50000端口时,却能成功建立连接,这种现象叫做「自连接」。
我们再通过netstat命令查看创建的连接是怎样的。
我们可以注意到,创建的连接的源端口和目的端口都是一样的。
原因分析
我们都知道,一条TCP连接主要是由源端口、源IP、目的端口、目的IP四部分组成的,我们称为「TCP socket四元组」。
当我们尝试对本机的一个端口创建连接时,四元组中的源IP、目的端口和目的IP已经确定了(源IP和目的IP都是本地IP,目的端口即是我们尝试请求的端口),至于源端口,是由系统为该连接分配的一个临时端口。
此时,如果目的端口未被监听,连接会有两种结果:
系统分配的源端口与目的端口不一样,则会报「Connection refused」的错误。
系统分配的源端口与目的端口一样,此时连接能创建成功,这种情况我们称为自连接。
发生自连接时,创建连接时包的交互过程如下。
系统分配给连接的源端口为50000,所以,tcp将通过50000端口发送一个SYN包给对端,并将连接状态置为「SYN_SENT」
由于50000端口同时也是目的端口,所以它会收到SYN报文,这时它会以为是对端同时也想创建连接,所以会回复SYN+ACK报文,并将连接状态置为「SYN_RCVD」
SYN+ACK报文也是会被50000端口自己接收的,它会以为这是对端给它的回复报文,所以认为握手成功,连接状态置为「ESTABLISHED」
自连接发生的条件
目的端口处于临时端口范围(linux临时端口范围由net.ipv4.ip_local_port_range决定)
目的端口未被监听
目的IP是本地IP
自连接的危害
假设有这样一个场景,一个机器上有A和B两个服务,服务A会请求服务B,服务B监听的端口属于临时端口。
有一天,服务B挂了,然后服务A一直在重连服务B,很不幸的发生了自连接。
这时候,服务B想重启时,就会发生端口占用的报错了。
避免自连接的手段
服务监听端口不要使用临时端口
如果感觉推送内容不错,不妨右下角点个在看,感谢支持!