1 故障描述:
一台Linux服务器作为服务端C,搭建服务的端口号为9527
一台Linux服务器作为客户端A,访问调用服务端C的业务
一台Linux服务器作为客户端B,访问调用服务端C的业务
客户端A能够正常访问服务端C的业务,telnet、tcping测试端口也正常,但客户端B无法正常访问服务端C的业务,telnet、tcping测试端口不通。
2 排查步骤:
a:服务端C的9527业务能被客户端A访问,起码说明服务正常启动,服务没问题
b:刚开始以为是网络配置问题,有可能服务器C限制了访问源地址,有可能是服务器安全组(云上虚拟机含安全组策略)限制源地址访问,网络设备(交换机、网闸)限制了源地址访问,排查发现配置均正常。
c:诡异的现象是:仅客户端A能够正常调用服务端C的9527端口,不管我们开通多少测试机,如何放宽网络策略,测试访问服务端C的9527端口都不成功。
d:流量抓包:在途径的网络设备(网闸)进行抓包,服务端C对客户端A、B的tcp syn包都返回ACK包,但对A发出的tcp syn包有响应,而对B不响应,不响应时,无法完成三次握手。详细查看发现发出的tcp syn包带有时间戳,因此怀疑时间戳问题导致的故障。抓包图片如下:
正常流量包含Seq,Win和Len字段
此次抓包发现包含TSval 和 TSecr 这两个参数
e:查看IPv4报文格式,时间戳(TCP Timestamps Option,TSopt)来源于TCP报文头部的Option选项。这个选项在 TCP 头部的位置如下所示,而时间戳报文包含类别(kind)、长度(Length)、发送方时间戳(TS value)、回显时间戳(TS Echo Reply)这四个参数。
点击刚刚抓包的报文,查看详情,正好存在发送方时间戳(TS value)、回显时间戳(TS Echo Reply),暂时判断为时间戳校验问题导致。
3 解决措施,关闭时间戳校验
情况为发送端(linux)与接收端(linux)同时开启了timestamp导致,此问题只要有一方不开启timestamp,就不会验证timestamp。因此现场将服务端的timestamp关闭,测试端口就通了(实际情况是尝试关闭了客户端B的时间戳校验并未成功,关闭服务端C时间戳,就成功了)。
关闭方法:不用重启生效:sysctl -w net.ipv4.tcp_timestamps=0
查看当前timestamps值: cat /proc/sys/net/ipv4/tcp_timestamps
开启方法:sysctl -w net.ipv4.tcp_timestamps=1
4 未解疑问
客户端A与服务器C原本同时开启了时间戳校验,为何就能通,且观察两台主机的时间相差了十多秒。而其他主机与服务器C的9527端口就是不能通,即使时间趋于一致。
对时间戳这个参数了解还不够深入,期待大佬们解惑。