好的,我知道这种情况有些不寻常,但是我需要使用原始套接字(在Linux中使用C语言)建立TCP连接(3次握手)——也就是说,我需要自己构造IP头和TCP头。我正在编写一个服务器(因此必须首先响应传入的SYN数据包),但出于某些原因,我似乎无法做到正确地处理它。是的,我知道SOCK_STREAM会自动处理这个问题,但由于某些原因我不想去深究,所以这不是一个选择。
我在网上找到的所有关于使用原始套接字的教程都只介绍如何构建SYN洪泛器,但这比实际建立TCP连接要容易一些,因为您不必根据原始数据包构建响应。我已经成功地运行了SYN洪泛器示例,并且可以通过原始套接字很好地读取传入的SYN数据包,但是我仍然无法创建有效的SYN/ACK响应以响应客户端发送的SYN。
那么,有没有人知道有关使用原始套接字的好教程,超越了创建SYN洪泛器的范畴,或者有没有一些代码可以使用SOCK_RAW而不是SOCK_STREAM来实现此目的?如果有的话,我将非常感激。
MarkR是完全正确的——问题在于内核在响应初始数据包时发送了复位数据包,因为它认为端口关闭了。内核比我更快地响应了请求,并且连接中断了。我已经使用tcpdump监视了连接——我应该更加细心地注意到有两个回复,其中之一是复位,这破坏了事情进展以及程序创建的响应。我太傻了!
最好的解决方案似乎是使用像MarkR建议的iptables规则来阻止出站数据包。然而,有一种比使用mark选项更简单的方法。我只匹配是否设置了复位TCP标志。在正常连接的过程中,这不太可能需要,而且如果我阻止正在使用的端口的所有出站复位数据包,对我的应用程序也没有什么影响。这有效地阻止了内核不需要的响应,但不影响我的数据包。如果我的程序侦听的端口是9999,则iptables规则如下:
iptables -t filter -I OUTPUT -p tcp --sport 9999 --tcp-flags RST RST -j DROP