好吧,我意识到这种情况有点不寻常,但我需要建立一个TCP连接(3次握手)只使用原始套接字(在C中,在linux中) - 即我需要自己构建IP头和TCP头.我正在写一个服务器(所以我必须先响应传入的SYN数据包),无论出于什么原因我似乎无法正确使用它.是的,我意识到SOCK_STREAM会为我处理这个,但由于我不想进入的原因,这不是一个选择.
我在网上找到的使用原始套接字的教程都描述了如何构建SYN flooder,但这比实际建立TCP连接要容易一些,因为您不必根据原始数据包构建响应.我已经让SYN flooder示例工作了,我可以从原始套接字读取传入的SYN数据包,但是我仍然无法从客户端创建对传入SYN的有效SYN/ACK响应.
那么,有没有人知道使用原始套接字的好教程不仅仅是创建SYN flooder,还是有人有一些代码可以做到这一点(使用SOCK_RAW,而不是SOCK_STREAM)?我会很感激.
MarkR是绝对正确的 - 问题是内核正在发送重置数据包以响应初始数据包,因为它认为端口已关闭.内核正在击败我的响应并且连接终止.我正在使用tcpdump监视连接 - 我本来应该更加敏锐,并注意到有两个回复,其中一个是重置,搞砸了事情,以及我的程序创建的响应.D'OH!
似乎最有效的解决方案是使用MarkR建议的iptables规则来阻止出站数据包.但是,正如建议的那样,使用标记选项比使用标记选项更容易.我只是匹配是否设置了重置TCP标志.在正常连接过程中,这不太可能是需要的,如果我阻止来自正在使用的端口的所有出站重置数据包,对我的应用程序来说并不重要.这有效地阻止了内核的不需要的响应,但不是我自己的数据包.如果我的程序正在侦听的端口是9999,那么iptables规则如下所示:
iptables -t filter -I OUTPUT -p tcp --sport 9999 --tcp-flags RST RST -j DROP
MarkR.. 11
您想在用户空间中实现TCP堆栈的一部分......这没关系,其他一些应用程序也这样做.
您将遇到的一个问题是内核将发送(通常是负面的,无用的)对传入数据包的回复.这会搞砸你试图启动的任何通信.
避免这种情况的一种方法是使用内核没有自己的IP堆栈的IP地址和接口 - 这很好,但你需要自己处理链路层的东西(特别是arp).这需要一个低于IPPROTO_IP,SOCK_RAW的套接字 - 你需要一个数据包套接字(我认为).
也可以使用iptables规则来阻止内核的响应 - 但是我宁愿怀疑这些规则也会以某种方式应用于你自己的数据包,除非你能设法让它们得到不同的处理(也许应用netfilter"mark"来你自己的包?)
阅读手册页
socket(7)ip(7)包(7)
这解释了适用于套接字类型的各种选项和ioctl.
当然,你需要一个像Wireshark这样的工具来检查发生了什么.您将需要多台计算机来测试它,我建议使用vmware(或类似的)来减少所需的硬件数量.
对不起,我不能推荐一个特定的教程.
祝好运.
您想在用户空间中实现TCP堆栈的一部分......这没关系,其他一些应用程序也这样做.
您将遇到的一个问题是内核将发送(通常是负面的,无用的)对传入数据包的回复.这会搞砸你试图启动的任何通信.
避免这种情况的一种方法是使用内核没有自己的IP堆栈的IP地址和接口 - 这很好,但你需要自己处理链路层的东西(特别是arp).这需要一个低于IPPROTO_IP,SOCK_RAW的套接字 - 你需要一个数据包套接字(我认为).
也可以使用iptables规则来阻止内核的响应 - 但是我宁愿怀疑这些规则也会以某种方式应用于你自己的数据包,除非你能设法让它们得到不同的处理(也许应用netfilter"mark"来你自己的包?)
阅读手册页
socket(7)ip(7)包(7)
这解释了适用于套接字类型的各种选项和ioctl.
当然,你需要一个像Wireshark这样的工具来检查发生了什么.您将需要多台计算机来测试它,我建议使用vmware(或类似的)来减少所需的硬件数量.
对不起,我不能推荐一个特定的教程.
祝好运.