Linux创建连接频繁中的临时端口

ip_local_port_range限制了临时端口的使用范围,当程序与对端要建立连接时,系统会随机分配一个这个范围内的未使用端口,查看当前设置的端口范围:

1
cat /proc/sys/net/ipv4/ip_local_port_range

如果需要更改这个范围,可以直接更改上面的文件,或者通过内核参数:

1
net.ipv4.ip_local_port_range

这个参数的文档描述如下:

ip_local_port_range - 2 INTEGERS
Defines the local port range that is used by TCP and UDP to
choose the local port. The first number is the first, the
second the last local port number.
If possible, it is better these numbers have different parity
(one even and one odd value).
Must be greater than or equal to ip_unprivileged_port_start.
The default values are 32768 and 60999 respectively.

以下命令可用于验证临时端口的使用:

1
while true;do telnet 127.0.0.1 50000; done

这里会产生TCP self connection问题。如果一个窗口比较难复现,可以多开几个窗口执行上述循环,直到self connection成功。

但有时我们需要ip_local_port_range范围的某些端口不被分配,这时我们可以使用如下参数:

1
net.ipv4.ip_local_reserved_ports

ip_local_reserved_ports - list of comma separated ranges
Specify the ports which are reserved for known third-party
applications. These ports will not be used by automatic port
assignments (e.g. when calling connect() or bind() with port
number 0). Explicit port allocation behavior is unchanged.
The format used for both input and output is a comma separated
list of ranges (e.g. “1,2-4,10-10” for ports 1, 2, 3, 4 and
10). Writing to the file will clear all previously reserved
ports and update the current list with the one given in the
input.

​ Note that ip_local_port_range and ip_local_reserved_ports
​ settings are independent and both are considered by the kernel
​ when determining which ports are available for automatic port
​ assignments.

​ You can reserve ports which are not in the current
​ ip_local_port_range, e.g.:
​ $ cat /proc/sys/net/ipv4/ip_local_port_range
​ 32000 60999
​ $ cat /proc/sys/net/ipv4/ip_local_reserved_ports
​ 8080,9148
​ although this is redundant. However such a setting is useful
​ if later the port range is changed to a value that will
​ include the reserved ports.

​ Default: Empty

比如要排查50000和51000到51100,更改这个内核参数即可:

1
sysctl -w net.ipv4.ip_local_reserved_ports=50000,51000-51100

对这个设置进行持久化,可以写入文件/etc/sysctl.conf里。

如果这时再执行如下循环,将不会再建立连接:

1
while true;do telnet 127.0.0.1 50000; done

参考: