数据包转发时遇到“TCP Dup ACK 14#1”的问题。
这是说第14帧的数据包丢了,“#1”表示该帧丢失的次数。
会出现这个问题的原因是我伪造回复的数据包时,TCP协议扩展头中的timestamps没有相应更新,导致接收端认为是重传包,直接丢弃了。这里就有了一个比较有趣的问题了,tcp通过seq和ack来判断数据包的丢失和重传,现在又会在timestamps中做重传的判断,如果这里不改,伪造的数据包时不会被接收的。
Timestamps 选项的作用
1 用来计算往返时间RTT。
发送方在发送报文段时把当前时钟的时间值放入时间戳字段,接收方在确认该报文段时把时间戳字段值复制到时间戳回送回答字段。因此,发送方在收到确认报文后,可以准确计算出RTT。时间戳是一个单调增长的值,接收方只需要回显收到的内容,因此是不需要关注时间戳的单元是什么,也不需要连接双发的时钟同步。
为什么需要用Timestamps计算RTT
TCP 在发送一个包时,会记录这个包的发送的时间 t1,用收到这个包的确认包时 t2 减去 t1 就可以得到这次的 RTT。这里有一个问题,如果发出的包出现重传,计算就变得复杂起来。无法得知收到的确认 ACK 是对第一次包还是重传包的的确认。
2 PAWS:防止回绕的序号。
我们知道序列号只有32位,而每增加2^32个序列号后就会重复使用原来用过的序列号。假设我们有一条高速网络,通信的主机双方有足够大的带宽用来快速的传输数据。例如1Gb/s(TCP 的窗口经过窗口缩放可以最高到 1GB(2^30))的速率发送报文段,则不到35秒钟数据字节的序列号就会重复。这样对TCP传输带来混乱的情况。这种情况之出现在高速链路上。而采用时间戳选项,可以很容易的分辨出相同序列号的数据报,哪个是最近发送,哪个是以前发送的。
在 Linux 上禁用 TCP 时间戳响应。
方法一:要将 net.ipv4.tcp_timestamps
的值设置为 0
,请运行 sysctl -w net.ipv4.tcp_timestamps=0
命令。
方法二:在默认 sysctl.conf
文件中添加 net.ipv4.tcp_timestamps=0
值。
echo 'net.ipv4.tcp_timestamps=0' >> /etc/sysctl.conf
修改完毕后执行
sysctl -p /etc/sysctl.conf
可以执行sysctl -a 查看配置项是否生效。