前言
網上關於 net.ipv4.ip_local_port_range 的值的效果眾說紛紜(下面所說的連接都假定使用的是相同的協議(都是 TCP 或 UDP)):
- 大部分文章都說這個值決定了客戶端的一個 ip 可用的端口數量,即一個 ip 最多只能創建 60K 多一點的連接(1025-65535),如果要突破這個限制需要客戶端機器綁定多個 ip。
- 還有部分文章說的是這個值決定的是 socket 四元組中的本地端口數量,即一個 ip 對同一個目標 ip+port 最多可以創建 60K 多一點連接,只要目標 ip 或端口不一樣就可以使用相同的本地端口,不一定需要多個客戶端 ip 就可以突破端口數量限制。
文檔 中的介紹也很模糊:
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 values) The default values are 32768 and 60999 respectively.
下面就來做一些實驗來確認這個選項的實際效果。
實驗環境:
$ uname -a Linux vagrant 4.15.0-29-generic #31-Ubuntu SMP Tue Jul 17 15:39:52 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
相同目標 ip 和相同目標端口下的端口數量限制
先設置 ip_local_port_range 的值為非常小的范圍:
$ echo "61000 61001" | sudo tee /proc/sys/net/ipv4/ip_local_port_range 61000 61001 $ cat /proc/sys/net/ipv4/ip_local_port_range 61000 61001
然后對相同 ip 和端口發送 tcp 請求。創建兩個連接,達到最大端口數量限制:
$ nohup nc 123.125.114.144 80 -v & [1] 16196 $ nohup: ignoring input and appending output to 'nohup.out' $ nohup nc 123.125.114.144 80 -v & [2] 16197 $ nohup: ignoring input and appending output to 'nohup.out' $ ss -ant |grep 10.0.2.15:61 ESTAB 0 0 10.0.2.15:61001 123.125.114.144:80 ESTAB 0 0 10.0.2.15:61000 123.125.114.144:80
然后再創建第三個連接,此時預期應該會失敗,因為超出的端口數量現在:
vagrant@vagrant:~$ nc 123.125.114.144 80 -v nc: connect to 123.125.114.144 port 80 (tcp) failed: Cannot assign requested address
可以看到確實如預期的失敗了。
相同目標 ip 不同目標端口
下面看看相同目標 ip 不同目標端口是否可以突破這個端口限制:
$ nohup nc 123.125.114.144 443 -v & [3] 16215 $ nohup: ignoring input and appending output to 'nohup.out' $ nohup nc 123.125.114.144 443 -v & [4] 16216 $ nohup: ignoring input and appending output to 'nohup.out' $ ss -ant |grep 10.0.2.15:61 ESTAB 0 0 10.0.2.15:61001 123.125.114.144:443 ESTAB 0 0 10.0.2.15:61001 123.125.114.144:80 ESTAB 0 0 10.0.2.15:61000 123.125.114.144:443 ESTAB 0 0 10.0.2.15:61000 123.125.114.144:80
可以看到相同目標 ip 不同目標端口下,每個目標端口都有一個獨立的端口限制,即,相同源 ip 的源端口是可以相同的。
按照推測這兩個目標端口應該只能創建四個連接,下面試試看:
$ ss -ant |grep 10.0.2.15:61 ESTAB 0 0 10.0.2.15:61001 123.125.114.144:443 ESTAB 0 0 10.0.2.15:61001 123.125.114.144:80 ESTAB 0 0 10.0.2.15:61000 123.125.114.144:443 ESTAB 0 0 10.0.2.15:61000 123.125.114.144:80 $ nc 123.125.114.144 443 -v nc: connect to 123.125.114.144 port 443 (tcp) failed: Cannot assign requested address
確實是不能再創建連接了,因為每個目標端口都達到了 ip_local_port_range 的限制。
多個目標 ip 相同目標端口
下面看一下多個目標 ip 相同目標端口下的情況:
$ nohup nc 220.181.57.216 80 -v & [5] 16222 $ nohup: ignoring input and appending output to 'nohup.out' $ nohup nc 220.181.57.216 80 -v & [6] 16223 $ nohup: ignoring input and appending output to 'nohup.out' $ nc 220.181.57.216 80 -v nc: connect to 220.181.57.216 port 80 (tcp) failed: Cannot assign requested address $ ss -ant |grep :80 SYN-SENT 0 1 10.0.2.15:61001 220.181.57.216:80 SYN-SENT 0 1 10.0.2.15:61000 220.181.57.216:80 SYN-SENT 0 1 10.0.2.15:61001 123.125.114.144:80 SYN-SENT 0 1 10.0.2.15:61000 123.125.114.144:80
可以看到,每個目標 ip 都有獨立的 ip_local_port_range 限制。
多個目標 ip 不同目標端口
下面看一下多個目標 ip 相同不同端口下的情況,按照前面的經驗兩個 ip 加兩個端口應該只能創建 8 個連接
$ nohup nc 123.125.114.144 80 -v & $ nohup nc 123.125.114.144 80 -v & $ nc 123.125.114.144 80 -v nc: connect to 123.125.114.144 port 80 (tcp) failed: Cannot assign requested address $ nohup nc 123.125.114.144 443 -v & $ nohup nc 123.125.114.144 443 -v & $ nc 123.125.114.144 443 -v nc: connect to 123.125.114.144 port 443 (tcp) failed: Cannot assign requested address $ nohup nc 220.181.57.216 80 -v & $ nohup nc 220.181.57.216 80 -v & $ nc 220.181.57.216 80 -v nc: connect to 220.181.57.216 port 80 (tcp) failed: Cannot assign requested address $ nohup nc 220.181.57.216 443 -v & $ nohup nc 220.181.57.216 443 -v & $ nc 220.181.57.216 443 -v nc: connect to 220.181.57.216 port 443 (tcp) failed: Cannot assign requested address $ ss -ant |grep 10.0.2.15:61 SYN-SENT 0 1 10.0.2.15:61001 220.181.57.216:80 ESTAB 0 0 10.0.2.15:61001 123.125.114.144:443 ESTAB 0 0 10.0.2.15:61000 220.181.57.216:443 SYN-SENT 0 1 10.0.2.15:61000 220.181.57.216:80 SYN-SENT 0 1 10.0.2.15:61001 123.125.114.144:80 ESTAB 0 0 10.0.2.15:61000 123.125.114.144:443 SYN-SENT 0 1 10.0.2.15:61000 123.125.114.144:80 ESTAB 0 0 10.0.2.15:61001 220.181.57.216:443
可以看到確實如預期的只能創建8個連接。
總結
那么是否就可以說前言中的第一種說法就是錯的呢,查了一下資料其實也不能說第一種說法是錯誤的:
- 當系統的內核版本小於 3.2 時,第一種說法是正確的
- 當系統的內核版本大於等於 3.2 時,第二種說法是正確的
參考資料
- kernel.org/doc/Documentation/networking/ip-sysctl.txt
- Tuning your Linux kernel and HAProxy instance for high loads
- Load Testing HAProxy (Part 2) – freeCodeCamp.org
- What is the theoretical maximum number of open TCP connections that a modern Linux box can have - Stack Overflow
- Coping with the TCP TIME-WAIT state on busy Linux servers | Vincent Bernat
- 'Re: Fix for rare EADDRNOTAVAIL error' - MARC
Reference:
https://mozillazg.com/2019/05/linux-what-net.ipv4.ip_local_port_range-effect-or-mean.html net.ipv4.ip_local_port_range 的值究竟影響了啥