TCP客户端在握手时不发送ACK

时间:2014-03-20 14:34:35

标签: tcp netfilter

我的测试环境

客户端

  • IP 192.168.0.2/24
  • gateway 192.168.0.1

服务器

  • IP 192.168.0.1/24
  • http服务在端口80上运行

当我尝试在服务器上托管网页时,一切都很顺利。

然后我在服务器上使用netfilter编写内核模块,如果源dest IP为192.168.1.1,则将dest IP更改为192.168.0.1,如果源IP为192.168.0.1,则将源IP更改为192.168.1.1 。我想您可以理解我只是假装服务器为客户端192.168.1.1。(IP头校验和TCP校验和已正确更改)

我在客户端使用网页浏览器(chrome,firefox ...)访问192.168.1.1并在客户端捕获数据包,结果如下:

192.168.0.2:someport_1 -> 192.168.1.1:80 [SYN]
192.168.1.1:80 -> 192.168.0.2:someport_1 [SYN, ACK]
192.168.0.2:someport_2 -> 192.168.1.1:80 [SYN]
192.168.1.1:80 -> 192.168.0.2:someport_2 [SYN, ACK]
192.168.0.2:someport_3 -> 192.168.1.1:80 [SYN]
192.168.1.1:80 -> 192.168.0.2:someport_3 [SYN, ACK]

我不知道为什么客户端永远不会发送TCP握手的最后一个ACK,有什么想法吗?

EDIT1:

现在我认为浏览器没有从服务器获取[SYN,ACK]数据包,虽然wireshark可以看到它,所以也许是因为操作系统(Windows7)放弃了[SYN, ACK]来自服务器的数据包。现在的问题是,为什么Windows会丢弃正确的[SYN,ACK]数据包?

2 个答案:

答案 0 :(得分:0)

您说IP校验和没问题,但是TCP校验和又是如何从包含源IP和目标IP的伪报头计算的呢?

答案 1 :(得分:0)

我犯了三个错误。

第一个是skb可以是非线性,这将导致从csum_partial()获得的校验和不正确。

第二个是我使用csum_tcpudp_magic()获取校验和,但忘记更改 skb-> ip_summed ,因此NIC将使用我的正确校验和作为tcp伪的部分校验和-header重新计算校验和,导致数据包中的校验和不正确。

第三个错误是我的wireshark似乎被设置为忽略tcp校验和,并且它总是将具有错误校验和的数据包显示为好的,而tcpdump将告诉我错误的校验和。