问题症状:
Linux服务器收到SYN请求报文后,不响应ACK,导致客户端建立TCP连接失败。
您可以通过netstat命令查看系统协议统计信息,发现很多请求因时间戳而被拒绝
通过帮助找出有相同的人遇到此问题:
是通过调整 sysctl -w netipv4.tcp tw recycle=0 来解决这个问题。
发现该问题是由 Linux TCP TW 回收 TCP 时间戳设置引起的。 如果在Linux内核源码中开启了TCP TW回收TCP时间戳,则同一源IP主机的套接字连接请求中的时间戳必须在60秒内递增。
我这边和其他同事通过公司的出口访问问题服务器(NAT网关只有1个IP地址),因为时间戳时间是从系统开机到当前时间,所以我和其他同事的时间戳肯定是不一样的; 根据 SYN 报文的源代码,当同时启用 TCP TW Recycle 和 TCP TimeStamp 时,Timestamp 较大的主机成功访问 servern,而 TimeStamp 较小的主机无法访问 servern。
已解决:回声"0" > /proc/sys/net/ipv4/tcp_tw_recycle
理论补充:1.净ipv4.tcp_timestamps
TCP时间戳的本质是记录数据包的发送时间。 基本步骤如下:
当发送方发送数据时,它会在数据包中放置一个时间戳(指示发送时间)。
接收方收到报文后,将接收到的时间戳返回给对应ACK报文的发送方
收发ACK报文后,可以使用NOW - ACK报文中的时间戳获取准确的RTT
时间戳是一个双向选项,当一方未启用时,它会停用双方。 例如,客户端发送的 SYN 数据包包含 timestamp 选项,但服务器未启用此选项。 回复的 syn-ack 没有 timestamp 选项,客户端后续回复的 ACK 没有 timestamp 选项。 当然,如果客户端发送的 SYN 数据包不包含时间戳,则时间戳将在两个方向上被禁用。
TCP 数据包中 Timestamp 的值是从系统启动时间到当前时间的(毫秒级)时间戳。
参数:0:已停用。
1:启用(系统默认值)。
2、net.ipv4.tcp_tw_recycle
处于 TCP 规范中指定的时间等待中的 TCP 连接必须等待 2 MSL 时间。 但是,在 Linux 中,如果启用了 TCP TW 回收,则 Time Wait 的 TCP 连接不会等待 2MSL 时间(RTO 或 60S),从而实现快速复用(**处于 Time Wait 状态的 TCP 连接)。 这可能会导致连接从以前的连接接收数据。 为此,Linux 会在启用 TCP TW 回收时记录时间等待连接的对等信息,包括 IP 地址和时间戳。 这样,当内核收到相同IP的SYN报文时,会比较时间戳,检查SYN报文的时间戳是否滞后,如果滞后,就会扔掉(以为是旧连接的数据)。 这在大多数情况下是可以的,但是对于我们实际的客户端-服务器服务,访问我们服务的用户一般位于NAT之后,如果多个用户在NAT之后访问同一服务,则可能会因时间戳滞后而丢失连接。
参数:0:禁用(系统默认值)。
1:已启用。 默认值:
使用默认值确定
查看内核参数。
方法一:使用“proc sys”目录,通过cat命令查看对应文件的内容。 “proc sys”目录是Linux内核启动后生成的伪目录,目录下的net文件夹存放了当前系统中所有有效的内核参数,目录树结构与参数的全称相关,如netipv4.TCP TW Recycle,对应 proc sys net IPv4 TCP TW recycle,文件内容为参数值。 cat /proc/sys/net/ipv4/tcp_tw_recycle
方法二:通过“etc sysctl”。conf“文件。 执行以下命令,查看当前系统中生效的所有参数。 /usr/sbin/sysctl -a
修改内核参数。
方法一:使用proc sys目录下的echo命令修改内核参数对应的文件。 该方法修改后的参数值仅在当前运行中生效,重启后会重置为原始参数值,一般用于临时校验。 要永久生效,请参阅方法 2。 echo "0" > /proc/sys/net/ipv4/tcp_tw_recycle。
方法二:通过“etc sysctl”。conf“文件。 该方法修改后的参数值永久生效。 (建议第二个选项)。