当我尝试在服务器上托管网页时,一切都很顺利。
然后我在服务器上使用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,有什么想法吗?
现在我认为浏览器没有从服务器获取[SYN,ACK]数据包,虽然wireshark可以看到它,所以也许是因为操作系统(Windows7)放弃了[SYN, ACK]来自服务器的数据包。现在的问题是,为什么Windows会丢弃正确的[SYN,ACK]数据包?
答案 0 :(得分:0)
您说IP校验和没问题,但是TCP校验和又是如何从包含源IP和目标IP的伪报头计算的呢?
答案 1 :(得分:0)
我犯了三个错误。
第一个是skb可以是非线性,这将导致从csum_partial()获得的校验和不正确。
第二个是我使用csum_tcpudp_magic()获取校验和,但忘记更改 skb-> ip_summed ,因此NIC将使用我的正确校验和作为tcp伪的部分校验和-header重新计算校验和,导致数据包中的校验和不正确。
第三个错误是我的wireshark似乎被设置为忽略tcp校验和,并且它总是将具有错误校验和的数据包显示为好的,而tcpdump将告诉我错误的校验和。