A和B之间经过一个ROS,这个ROS上有两块网卡,经过长途电路互相连接,A在10.10.10网段,B在10.10.11网段,前几天发现突然10.网段的一台机器无访问访问B(11.152)的TCP端口,但可以PING通,10网段的其它机器可以访问11.152,当时怀疑152的问题,但是其它机器又可以访问,所以最后也不知道到底是什么问题了,抓包发现A(10.38)上访问B的TCP端口时发现收到A的SYN包,但是没有给A回应,然后网上搜索了下,发现了是TCP的时间戳的问题。
正常TCP访问:
不正常时:
从抓包不正常访问的截图中可以清晰地看到,客户端的59984端口连续2次向服务器的50500端口发送SYS包,请求建立TCP连接。但服务器却未回应,没有将回应包发送到客户端的59984端口,因此客户端认为建立TCP连接失败,表现出现的现象就是连接断线或网络断开等。
以下为引用:
经查询,对发生这种服务器不响应客户端SYS包请求的解释如下:
当客户端发出的SYS包带有时间戳的情况下,经过NAT转换后,如果使用的端口在之前已经使用过,而且之前相同端口的SYS包中携带时间戳大于本次SYS包中的时间戳。在这种情况下,Linux系统内核将会直接丢弃本次SYS包,造成本次链接无法正常完成TCP/IP的3次握手。【该功能和rfc1323有关:】
上面的说法可能有些绕口,不容易理解,举个例子来说明一下。假如处于同一内部网络的主机A和主机B通过NAT网关(1个ip地址,且端口也相同)访问serverN,由于timestamp时间为系统启动到当前的时间,因此,主机A和主机B的timestamp不相同;这时,timestamp大的主机访问serverN成功,而timestmap小的主机则访问serverN失败。
解决该问题的方法为:关闭TCP的timestmap功能,即不启用时间戳。
# vi /etc/sysctl.conf,设置
net.ipv4.tcp_timestamps = 0
## 默认情况下,该值为1,即启用
然后执行# sysctl -p 使配置生效,这样就不会出现间歇性断线的情况了。