Linux TCP连接建立过程超时的参数调整
1. 概述
github项目地址:https://github.com/superwujc
尊重原创,欢迎转载,注明出处:https://my.oschina.net/superwjc/blog/1819254
TCP的连接建立过程通常称为三次握手(three-way handshake),即客户端与服务端彼此交换用于建立连接的初始SYN segment与ACK。
连接建立过程中,任一端出现接收不到对端ACK的情况时,都将导致本端重传初始SYN segment,Linux内核为该情况设置了重传间隔与重传次数:
- 重传间隔:若当前为第N次重传,则与上一次发送或重传的间隔时间为2的(N -1)次方秒,但最长间隔不超过120秒;内核的TCP_TIMEOUT_INIT/TCP_RTO_MIN/TCP_RTO_MAX宏分别定义了间隔时间的初始值/最小值/最大值
- 重传次数:客户端由tcp_syn_retries指定,对应的proc文件为/proc/sys/net/ipv4/tcp_syn_retries,sysctl参数为net.ipv4.tcp_syn_retries;服务端由tcp_synack_retries指定,对应的proc文件为/proc/sys/net/ipv4/tcp_synack_retries,sysctl参数为net.ipv4.tcp_synack_retries
2. 示例
操作系统:CentOS Linux release 7.5.1804 (Core)
内核版本:3.10.0-862.2.3.el7.x86_64
服务端IP:22.99.22.111
客户端IP:22.99.22.101
示例程序详见 Linux TCP那些事儿之被动套接字(一)
服务端启动程序:
# ./tcp_server -b 1024 &
客户端启动程序:
# ./tcp_client -i 22.99.22.111 -p 8888 -n 1 &
服务端与客户端分别启动tcpdump观察连接情况:
# tcpdump -i eth0 -nn -S host 22.99.22.111 and host 22.99.22.101 and tcp
2.1 – 正常连接
服务端与客户端的tcpdump输出:
21:40:49.989951 IP 22.99.22.101.38118 > 22.99.22.111.8888: Flags [S], seq 231965702, win 29200, options [mss 1460,sackOK,TS val 11012209 ecr 0,nop,wscale 7], length 0 21:40:49.989998 IP 22.99.22.111.8888 > 22.99.22.101.38118: Flags [S.], seq 513997240, ack 231965703, win 28960, options [mss 1460,sackOK,TS val 14396437 ecr 11012209,nop,wscale 7], length 0 21:40:49.990223 IP 22.99.22.101.38118 > 22.99.22.111.8888: Flags [.], ack 513997241, win 229, options [nop,nop,TS val 11012210 ecr 14396437], length 0
21:40:49.991145 IP 22.99.22.101.38118 > 22.99.22.111.8888: Flags [S], seq 231965702, win 29200, options [mss 1460,sackOK,TS val 11012209 ecr 0,nop,wscale 7], length 0 21:40:49.991499 IP 22.99.22.111.8888 > 22.99.22.101.38118: Flags [S.], seq 513997240, ack 231965703, win 28960, options [mss 1460,sackOK,TS val 14396437 ecr 11012209,nop,wscale 7], length 0 21:40:49.991541 IP 22.99.22.101.38118 > 22.99.22.111.8888: Flags [.], ack 513997241, win 229, options [nop,nop,TS val 11012210 ecr 14396437], length 0
查看连接状态,两端均显示连接已建立
# ss -atn | grep 8888 LISTEN 1 128 *:8888 *:* ESTAB 0 0 22.99.22.111:8888 22.99.22.101:38118
# ss -atn | grep 8888 ESTAB 0 0 22.99.22.101:38118 22.99.22.111:8888
2.2 – 客户端超时
在服务端添加防火墙规则,丢弃向客户端发送的syn+ack
# iptables -I OUTPUT -p tcp --destination 22.99.22.101 --tcp-flags ALL ACK,SYN -j DROP # # iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination DROP tcp -- anywhere 22.99.22.101 tcp flags:FIN,SYN,RST,PSH,ACK,URG/SYN,ACK
客户端设置重传次数,默认为6,修改为4
# cat /proc/sys/net/ipv4/tcp_syn_retries 6 # echo 4 > /proc/sys/net/ipv4/tcp_syn_retries # cat /proc/sys/net/ipv4/tcp_syn_retries 4
再次启动服务端与客户端程序,两端的tcpdump输出均显示客户端发生了4次初始SYN的重传,每次间隔分别为1s/2s/4s/8s,总间隔为15s
21:49:29.425637 IP 22.99.22.101.38120 > 22.99.22.111.8888: Flags [S], seq 1034503734, win 29200, options [mss 1460,sackOK,TS val 11531645 ecr 0,nop,wscale 7], length 0 21:49:30.428747 IP 22.99.22.101.38120 > 22.99.22.111.8888: Flags [S], seq 1034503734, win 29200, options [mss 1460,sackOK,TS val 11532648 ecr 0,nop,wscale 7], length 0 21:49:32.433200 IP 22.99.22.101.38120 > 22.99.22.111.8888: Flags [S], seq 1034503734, win 29200, options [mss 1460,sackOK,TS val 11534652 ecr 0,nop,wscale 7], length 0 21:49:36.437044 IP 22.99.22.101.38120 > 22.99.22.111.8888: Flags [S], seq 1034503734, win 29200, options [mss 1460,sackOK,TS val 11538656 ecr 0,nop,wscale 7], length 0 21:49:44.454342 IP 22.99.22.101.38120 > 22.99.22.111.8888: Flags [S], seq 1034503734, win 29200, options [mss 1460,sackOK,TS val 11546673 ecr 0,nop,wscale 7], length 0
21:49:29.426515 IP 22.99.22.101.38120 > 22.99.22.111.8888: Flags [S], seq 1034503734, win 29200, options [mss 1460,sackOK,TS val 11531645 ecr 0,nop,wscale 7], length 0 21:49:30.429581 IP 22.99.22.101.38120 > 22.99.22.111.8888: Flags [S], seq 1034503734, win 29200, options [mss 1460,sackOK,TS val 11532648 ecr 0,nop,wscale 7], length 0 21:49:32.434015 IP 22.99.22.101.38120 > 22.99.22.111.8888: Flags [S], seq 1034503734, win 29200, options [mss 1460,sackOK,TS val 11534652 ecr 0,nop,wscale 7], length 0 21:49:36.437559 IP 22.99.22.101.38120 > 22.99.22.111.8888: Flags [S], seq 1034503734, win 29200, options [mss 1460,sackOK,TS val 11538656 ecr 0,nop,wscale 7], length 0 21:49:44.454826 IP 22.99.22.101.38120 > 22.99.22.111.8888: Flags [S], seq 1034503734, win 29200, options [mss 1460,sackOK,TS val 11546673 ecr 0,nop,wscale 7], length 0
查看连接状态,服务端的syn+ack由于被自身drop而一直处于LISTEN状态,客户端在重传期间处于SYN-SENT状态,且超过重传次数后因连接超时而返回
# ss -atn | grep 8888 LISTEN 0 128 *:8888 *:*
# ss -atn | grep 8888 SYN-SENT 0 1 22.99.22.101:38120 22.99.22.111:8888 # connect() failed: Connection timed out
2.3 – 服务端超时
在客户端添加防火墙规则,丢弃向服务端发送的ack
# iptables -I OUTPUT -p tcp --destination 22.99.22.111 --dport 8888 --tcp-flags ALL ACK -j DROP # # iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination DROP tcp -- anywhere 22.99.22.111 tcp dpt:ddi-tcp-1 flags:FIN,SYN,RST,PSH,ACK,URG/ACK
客户端设置重传次数,默认为5,修改为3
# sysctl net.ipv4.tcp_synack_retries net.ipv4.tcp_synack_retries = 5 # [root@localhost code]# sysctl -w net.ipv4.tcp_synack_retries=3 net.ipv4.tcp_synack_retries = 3 # # sysctl net.ipv4.tcp_synack_retries net.ipv4.tcp_synack_retries = 3
再次启动服务端与客户端程序,两端的tcpdump输出均显示服务端发生了3次初始SYN的重传,每次间隔分别为1s/2s/4s,总间隔为7s
22:03:56.982987 IP 22.99.22.101.38122 > 22.99.22.111.8888: Flags [S], seq 985103784, win 29200, options [mss 1460,sackOK,TS val 12399201 ecr 0,nop,wscale 7], length 0 22:03:56.983034 IP 22.99.22.111.8888 > 22.99.22.101.38122: Flags [S.], seq 703914964, ack 985103785, win 28960, options [mss 1460,sackOK,TS val 15783430 ecr 12399201,nop,wscale 7], length 0 22:03:57.985014 IP 22.99.22.111.8888 > 22.99.22.101.38122: Flags [S.], seq 703914964, ack 985103785, win 28960, options [mss 1460,sackOK,TS val 15784432 ecr 12399201,nop,wscale 7], length 0 22:03:59.993905 IP 22.99.22.111.8888 > 22.99.22.101.38122: Flags [S.], seq 703914964, ack 985103785, win 28960, options [mss 1460,sackOK,TS val 15786441 ecr 12399201,nop,wscale 7], length 0 22:04:04.008496 IP 22.99.22.111.8888 > 22.99.22.101.38122: Flags [S.], seq 703914964, ack 985103785, win 28960, options [mss 1460,sackOK,TS val 15790456 ecr 12399201,nop,wscale 7], length 0
22:03:56.983313 IP 22.99.22.101.38122 > 22.99.22.111.8888: Flags [S], seq 985103784, win 29200, options [mss 1460,sackOK,TS val 12399201 ecr 0,nop,wscale 7], length 0 22:03:56.983746 IP 22.99.22.111.8888 > 22.99.22.101.38122: Flags [S.], seq 703914964, ack 985103785, win 28960, options [mss 1460,sackOK,TS val 15783430 ecr 12399201,nop,wscale 7], length 0 22:03:57.985870 IP 22.99.22.111.8888 > 22.99.22.101.38122: Flags [S.], seq 703914964, ack 985103785, win 28960, options [mss 1460,sackOK,TS val 15784432 ecr 12399201,nop,wscale 7], length 0 22:03:59.994857 IP 22.99.22.111.8888 > 22.99.22.101.38122: Flags [S.], seq 703914964, ack 985103785, win 28960, options [mss 1460,sackOK,TS val 15786441 ecr 12399201,nop,wscale 7], length 0 22:04:04.009283 IP 22.99.22.111.8888 > 22.99.22.101.38122: Flags [S.], seq 703914964, ack 985103785, win 28960, options [mss 1460,sackOK,TS val 15790456 ecr 12399201,nop,wscale 7], length 0
查看连接状态,服务端的初始SYN被客户端丢弃而在重传期间一直处于SYN-RECV状态,客户端已接收到服务端对初始SYN的ACK确认而处于ESTAB状态,导致半开(half-open)连接
# ss -atn | grep 8888 LISTEN 0 128 *:8888 *:* SYN-RECV 0 0 22.99.22.111%if355612354:8888 22.99.22.101:38122
# ss -atn | grep 8888 ESTAB 0 0 22.99.22.101:38122 22.99.22.111:8888
原文地址:https://my.oschina.net/superwjc/blog/1819254