与SOCK_RAW套接字的TCP握手

好吧,我意识到这种情况有点不寻常,但我需要build立一个TCP连接(三次握手),只使用原始套接字(在C中,在Linux中) – 即我需要自己构造IP头和TCP头。 我写了一个服务器(所以我必须首先响应传入的SYN数据包),无论出于什么原因,我似乎无法做到正确。 是的,我意识到一个SOCK_STREAM将为我处理这个问题,但由于我不想进入的原因不是一个选项。

我在网上find的关于使用原始套接字的教程都描述了如何构build一个SYN flooder,但是这实际上比build立TCP连接要容易一些,因为您不必根据原始数据包构build响应。 我已经得到了SYN flooder的例子工作,我可以从原始套接字读取传入的SYN包,但我仍然无法创build一个有效的SYN / ACK响应来自客户端的传入SYN。

那么,有没有人知道使用原始套接字,不仅仅是创build一个SYN flooder,或者是否有人可以做到这一点(使用SOCK_RAW,而不是SOCK_STREAM)的代码? 我会很感激。


MarkR是绝对正确的 – 问题在于内核正在发送重置数据包以响应初始数据包,因为它认为端口已closures。 内核正在殴打我的响应和连接死亡。 我正在使用tcpdump来监视连接 – 我应该更加细心,并且注意到有两个回复,其中一个是重新设置,以及我的程序创build的响应。 D'OH!

似乎最好的解决scheme是使用MarkRbuild议的iptables规则来阻止出站数据包。 但是,如build议的那样,使用标记选项有一个更简单的方法。 我只是匹配是否重置TCP标志设置。 在正常连接的过程中,这不太可能是需要的,如果我阻塞所有正在使用的端口的出站重置数据包,对我的应用程序来说并不重要。 这有效地阻止了内核的不需要的响应,但不是我自己的数据包。 如果我的程序监听的端口是9999,那么iptables规则如下所示:

iptables -t filter -I OUTPUT -p tcp --sport 9999 --tcp-flags RST RST -j DROP 

Solutions Collecting From Web of "与SOCK_RAW套接字的TCP握手"

你想在用户空间中实现一部分TCP堆栈…这是可以的,其他一些应用程序可以这样做。

你会遇到的一个问题是,内核将发送(通常是负面的,无用的)回复传入的数据包。 这将会破坏您尝试启动的任何通讯。

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

使用iptables规则阻止内核的响应也是可能的,但是我宁愿怀疑这些规则也适用于你自己的数据包,除非你能设法让它们得到不同的处理(也许应用一个netfilter“标记”你自己的包?)

阅读手册页

socket(7)ip(7)packet(7)

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

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

对不起,我不能推荐一个特定的教程。

祝你好运。

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

希望对某人有所帮助。

我无法帮助你在任何教程。

但是我可以给你一些关于你可以用来协助调试的工具的建议。

首先,根据bmdhacks的建议,给自己一个wireshark (或tcpdump的副本 – 但wireshark更容易使用)。 捕捉一个很好的握手。 确保你保存了这个。

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

接下来,让自己的tcpreplay的副本。 这还应该包括一个名为“tcprewrite”的工具。 tcprewrite将允许您将以前保存的捕获文件分为两个握手的每一方。 然后,您可以使用tprep来回放握手的一面,以便您可以使用一组一致的数据包进行播放。

然后你使用wireshark(再次)来检查你的回应。

我没有教程,但是最近我使用Wireshark来很好的调试我正在做的一些原始套接字编程。 如果您捕获了您要发送的数据包,wireshark将会很好地向您显示它们是否格式错误。 这对比较正常的连接也很有用。

在netinet / ip.h和netinet / tcp.h中分别声明了IP和TCP头文件。 你可能想看看在这个目录中的其他标题额外的宏和东西可能是有用的。

您发送一个包含SYN标志和一个随机序列号(x)的数据包。 你应该从另一端收到一个SYN + ACK。 这个数据包将有一个确认号(y),表示另一方希望接收的下一个序列号以及另一个序列号(z)。 您发回一个序列号为x + 1和ack编号为z + 1的ACK包来完成连接。

您还需要确保您计算适当的TCP / IP校验和,并填写您发送的数据包的标头的其余部分。 另外,不要忘记主机和网络字节顺序。

TCP是在RFC 793中定义的,可在此处找到: http : //www.faqs.org/rfcs/rfc793.html

取决于你想要做什么,可能更容易让现有的软件为你处理TCP握手。

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

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