与SOCK_RAW套接字进行TCP握手

时间:2008-09-21 05:43:07

标签: linux network-programming

好的,我意识到这种情况有点不寻常,但我需要建立一个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

7 个答案:

答案 0 :(得分:11)

您希望在用户空间中实现TCP堆栈的一部分......这没关系,其他一些应用也是如此。

您将遇到的一个问题是内核将发送(通常是否定的,无用的)对传入数据包的回复。这会搞砸你试图启动的任何通信。

避免这种情况的一种方法是使用内核没有自己的IP堆栈的IP地址和接口 - 这很好,但你需要自己处理链路层的东西(特别是arp)。这需要一个低于IPPROTO_IP,SOCK_RAW的套接字 - 你需要一个数据包套接字(我认为)。

也可以使用iptables规则来阻止内核的响应 - 但我更倾向于怀疑规则将以某种方式应用于您自己的数据包,除非您能够设法以不同的方式处理它们(可能应用netfilter“标记“你自己的数据包?”

阅读手册页

插座(7) IP(7) 分组(7)

解释了适用于套接字类型的各种选项和ioctl。

当然,你需要一个像Wireshark这样的工具来检查发生了什么。你需要几台机器来测试它,我建议使用vmware(或类似的)来减少所需的硬件数量。

抱歉,我不推荐具体的教程。

祝你好运。

答案 1 :(得分:4)

我意识到这是一个旧线程,但这里的教程超出了普通的SYN flooders:http://www.enderunix.org/docs/en/rawipspoof/

希望它对某人有所帮助。

答案 2 :(得分:2)

我无法帮助你完成任何教程。

但我可以就您可以用来帮助调试的工具提供一些建议。

首先,正如bmdhacks建议的那样,给自己一份wireshark(或tcpdump - 但wireshark更容易使用)。抓住好握手。确保保存此内容。

捕获失败的一次握手。 Wireshark有很好的数据包解析和错误检查,所以如果有一个简单的错误,它可能会告诉你。

接下来,给自己一份tcpreplay。这还应包括一个名为“tcprewrite”的工具。 tcprewrite将允许您将先前保存的捕获文件拆分为两个 - 一个用于握手的每一侧。 然后,您可以使用tcpreplay播放握手的一侧,以便您可以使用一组一致的数据包。

然后你再次使用wireshark检查你的回答。

答案 3 :(得分:1)

我没有教程,但我最近使用Wireshark来调试我正在做的一些原始套接字编程。如果您捕获了正在发送的数据包,wireshark会很好地向您显示它们是否格式不正确。它也可用于与普通连接进行比较。

答案 4 :(得分:0)

在netinet / ip.h&中声明了IP和TCP标头的结构。 netinet / tcp.h分别。您可能需要查看此目录中的其他标题以获取额外的宏和&可能有用的东西。

您发送的数据包设置了SYN标志和随机序列号(x)。您应该从另一方收到SYN + ACK。该分组将具有确认号(y),其指示另一方期望接收的下一个序列号以及另一个序列号(z)。您发回一个序列号为x + 1且确认号为z + 1的ACK数据包以完成连接。

您还需要确保计算适当的TCP / IP校验和&填写您发送的数据包的剩余部分。另外,不要忘记像host和amp;网络字节顺序。

TCP在RFC 793中定义,可在此处获取:http://www.faqs.org/rfcs/rfc793.html

答案 5 :(得分:0)

根据您尝试的操作,可能更容易让现有软件为您处理TCP握手。

一个开源IP堆栈是lwIP(http://savannah.nongnu.org/projects/lwip/),它提供完整的tcp / ip堆栈。使用SOCK_RAW或pcap可以在用户模式下运行它。

答案 6 :(得分:0)

如果你使用原始套接字,如果你使用不同的源mac地址发送到实际的套接字,linux将忽略响应数据包而不发送第一个。