繁体   English   中英

带SOCK_RAW套接字的TCP握手

[英]TCP handshake with SOCK_RAW socket

好的,我意识到这种情况有些不寻常,但是我需要仅使用原始套接字(在C中,在Linux中)建立TCP连接(三向握手),即我需要自己构造IP标头和TCP标头。 我正在编写服务器(因此我必须首先响应传入的SYN数据包),无论出于什么原因,我似乎都无法正确处理它。 是的,我意识到SOCK_STREAM会为我处理此问题,但是由于某些原因,我不想进入该选项,这是不可行的。

我在网上找到的有关使用原始套接字的教程都描述了如何构建SYN泛洪器,但这比实际建立TCP连接要容易一些,因为您不必基于原始数据包构造响应。 我已经使用了SYN Flooder示例,并且可以从原始套接字读取传入的SYN数据包,但是我仍然无法为从客户端传入的SYN创建有效的SYN / ACK响应。

那么,有谁知道关于使用原始套接字的优秀教程,而不仅仅是创建SYN泛洪器,或者没有人有一些代码可以做到这一点(使用SOCK_RAW,而不是SOCK_STREAM)? 我会很感激。


MarkR绝对正确-问题在于内核正在发送重置数据包以响应初始数据包,因为它认为端口已关闭。 内核是打我的反应和连接模具。 我已经在使用tcpdump来监视连接了-我应该更加观察并注意到,有两个答复,其中之一是重置,这使事情搞砸了,还有我的程序创建的响应。 D'OH!

这似乎工作最好的解决办法是使用iptables规则,通过MarkR的建议,以阻止出站数据包。 但是,正如建议的那样,有一种比使用mark选项更简单的方法。 我只是匹配是否设置了重置TCP标志。 在正常连接过程中,这不太可能需要,并且如果我阻止正在使用的端口上的所有出站重置数据包,则对我的应用程序来说并不重要。 这有效地阻止了内核的有害响应,但阻止了我自己的数据包。 如果我的程序正在侦听的端口是9999,则iptables规则如下所示:

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

您想在用户空间中实现TCP堆栈的一部分...没关系,其他一些应用程序也可以做到这一点。

您会遇到的一个问题是,内核将对传入的数据包发出(通常是负面的,无助的)回复。 这将搞砸您尝试启动的所有通信。

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

也可以使用iptables规则阻止内核的响应-但我怀疑规则也将以某种方式应用于您自己的数据包,除非您可以设法对它们进行不同处理(也许将netfilter“ mark”应用于您自己的数据包?)

阅读手册页

套接字(7)ip(7)数据包(7)

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

当然,您将需要诸如Wireshark之​​类的工具来检查正在发生的事情。 您将需要多台计算机进行测试,我建议使用vmware(或类似软件)以减少所需的硬件数量。

抱歉,我不能推荐特定的教程。

祝好运。

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

希望这可能对某人有所帮助。

我无法在任何教程上为您提供帮助。

但是,我可以为您提供一些建议,以帮助您进行调试。

首先,正如bmdhacks所建议的那样,给自己准备一份wireshark的副本(或tcpdump-但wireshark易于使用)。 握手良好。 确保您保存此。

捕获失败的握手之一。 Wireshark具有相当不错的数据包解析和错误检查功能,因此,如果存在直接错误,它可能会告诉您。

接下来,获取一份tcpreplay副本。 它还应包括一个名为“ tcprewrite”的工具。 tcprewrite将允许您将以前保存的捕获文件分为两部分-握手的每一侧。 然后,您可以使用tcpreplay播放握手的一侧,因此您可以使用一组一致的数据包。

然后,您再次使用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

如果您使用的是原始套接字,则如果您使用与实际的套接字不同的源mac地址进行发送,则linux将忽略响应数据包,而不发送rst。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM