【TCP/IP】端口未监听,还能访问成功?

1,722 阅读2分钟

现象

直接上图👇

file

可以发现,本地没监听50000端口的服务,但是尝试连接本地50000端口时,却能成功建立连接,这种现象叫做「自连接」

我们再通过netstat命令查看创建的连接是怎样的👇

file

我们可以注意到,创建的连接的源端口和目的端口都是一样的

原因分析

我们都知道,一条TCP连接主要是由源端口、源IP、目的端口、目的IP四部分组成的,我们称为「TCP socket四元组」。

当我们尝试对本机的一个未被监听的端口创建连接时,四元组中的源IP、目的端口和目的IP已经确定了(源IP和目的IP都是本地IP,目的端口即是我们尝试请求的端口),至于源端口,是由系统为该连接分配的一个临时端口。

此时,连接会有两种结果:

  • 系统分配的源端口与目的端口不一样,则会报「Connection refused」的错误。
  • 系统分配的源端口与目的端口一样,此时连接能创建成功,这种情况我们称为自连接

发生自连接时,创建连接时包的交互过程如下

file

  1. 系统分配给连接的源端口为50000,所以,tcp将通过50000端口发送一个SYN包给对端,并将连接状态置为「SYN_SENT」
  2. 由于50000端口同时也是目的端口,所以它会收到SYN报文,这时它会以为是对端同时也想创建连接,所以会回复SYN+ACK报文,并将连接状态置为「SYN_RCVD」
  3. SYN+ACK报文也是会被50000端口自己接收的,它会以为这是对端给它的回复报文,所以认为握手成功,连接状态置为「ESTABLISHED」

自连接发生的条件

  1. 目的端口处于临时端口范围(linux临时端口范围由net.ipv4.iplocalport_range决定)
  2. 目的端口未被监听
  3. 目的IP是本地IP

自连接的危害

假设有这样一个场景,一个机器上有A和B两个服务,服务A会请求服务B,服务B监听的端口属于临时端口

有一天,服务B挂了,然后服务A一直在重连服务B,很不幸的发生了自连接。

这时候,服务B想重启时,就会发生端口占用的报错了

避免自连接的手段

  • 服务监听端口不要使用临时端口

转载请注明出处