使用Python原始套接字进行TCP握手

4
我正在使用Python原始套接字实现TCP握手。然而,Linux内核试图处理这个协议的某些方面,所以有些麻烦。例如,当我发送一个SYN数据包时,服务器会响应一个SYN,ACK数据包;此时内核会自动发送一个RST数据包来重置连接。我通过使用以下iptables规则来丢弃所有这样的重置数据包来解决这个问题:
-A OUTPUT -p tcp -m tcp --sport 999 --tcp-flags RST RST -j DROP

现在我希望接收服务器发送的SYN, ACK数据包并将其打印出来。但是,当我执行以下操作时,我什么也没有收到:

a = self.s.recvfrom(4096)

我怀疑内核在我使用套接字接收之前就丢弃了SYN、ACK。有人知道一个合理的解决方法吗?

你会考虑使用Scapy吗?https://github.com/secdev/scapy/ - John Zwinck
Scapy能否恢复和解析SYN、ACK包?我认为这个数据包被内核丢弃了。 - SivaDotRender
我不知道,我建议它作为一个可能的高级库供您使用(或至少学习),而不是试图从头开始全部自己完成。 - John Zwinck
@JohnZwinck 我验证了scapy正在执行的操作。看起来它实现了一种数据包捕获方法,类似于rodolk在下面建议的方法。 - SivaDotRender
3个回答

1

虽然我希望有更方便的解决方案,但其中一种方法是使用iptables将传入的TCP Syn数据包传递给nfqueue。Nfqueue已有现有的pythonbindings, 因此使用它不应该成为问题。

这个想法是在这些数据包到达内核的TCP实现之前捕获所有传入的TCP Syns。然后将这些数据包传递给nfqueue,您的用户应用程序可以监控它。对于每个从nfqueue获取的数据包,您的应用程序将不得不决定(return a verdict)是否处理数据包本身(即将数据包丢弃,就操作系统而言),还是将其传递给常规的TCP实现。

我知道这种方法确实有效,但它很繁琐。


目前来看,这听起来是最合理的解决方案。 - SivaDotRender

1
您可以使用libpcap,在Python中似乎有这个模块:http://pylibpcap.sourceforge.net/ 或者这个:https://pypi.python.org/pypi/pypcap 使用pcap,您可以注册来自内核的消息。通过从应用程序提供正确的过滤器,您可以接收来自内核的TCP段。我曾在C中使用过libpcap,我认为您可以以同样的方式使用指定的模块。对我来说,这是最好的解决方案,因为您可以从应用程序中以相当标准的方式处理它。
为了避免内核响应RST,您的iptables解决方案对我来说是最好的。

1
由于您正在使用原始数据包进行操作,为什么不创建自己的MAC地址和IP地址呢?您需要将适配器置于混杂模式才能接收数据包,但如果这样做,内核不应向您的传入数据包发送任何响应,因为它们看起来是寻址到“其他系统”的。这使得从其他数据包中过滤出您关心的数据包变得很容易。
您还需要适当地响应ARP请求,以便其他系统可以找到您的MAC地址。如果您需要DHCP来获取IP地址,则还需要处理这些交互。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接