简体   繁体   English

使用python RAW套接字的TCP握手

[英]TCP handshake using python RAW sockets

I am implementing a TCP handshake using python RAW sockets. 我正在使用python RAW套接字实现TCP握手。 The Linux kernel is however being quite annoying because it attempts to handle certain aspects of this protocol. 但是,Linux内核非常烦人,因为它试图处理该协议的某些方面。

For example, when I send a SYN packet, the server responded with a SYN, ACK packet; 例如,当我发送SYN数据包时,服务器以SYN ACK数据包作为响应; to which the kernel automatically responds with a RST packet resetting the connection. 内核使用RST数据包自动响应以重置连接。 I overcame this my dropping all such reset packets using the following iptable rule: 我克服了这个问题,使用以下iptable规则丢弃了所有此类重置数据包:

-A OUTPUT -p tcp -m tcp --sport 999 --tcp-flags RST RST -j DROP

Now I want to receive the SYN, ACK packet sent by the server and print it out. 现在,我想接收服务器发送的SYN,ACK数据包并打印出来。 But I receive nothing when I do the following: 但是,当我执行以下操作时,我什么也没收到:

a = self.s.recvfrom(4096)

I suspect that the kernel is dropping the SYN, ACK before I can recv it using my socket. 我怀疑内核会先丢弃SYN,ACK,然后才能使用套接字接收它。 Does anyone know a reasonable workaround? 有谁知道合理的解决方法?

While I hope that someone comes up with a more convenient solution, one way to do it would be to use iptables to pass incoming TCP Syn packets to an nfqueue . 尽管我希望有人能提出一个更方便的解决方案,但一种实现方法是使用iptables将传入的TCP Syn数据包传递给nfqueue Nfqueue has existing python bindings , so using it shouldn't be an issue. Nfqueue具有现有的python 绑定 ,因此使用它应该不是问题。

The idea is to catch all incoming TCP Syns before they reach the kernel's TCP implementation. 这个想法是在所有传入的TCP Syn到达内核的TCP实现之前捕获它们。 Then pass these packets to the nfqueue which your userland app can monitor. 然后将这些数据包传递到您的userland应用程序可以监视的nfqueue。 For each packet your app will get from the nfqueue, it will have to decide ( return a verdict ) of whether to handle the packet itself (ie drop the packet as far as the OS is concerned) or pass it along to the regular TCP implementation. 对于您的应用将从nfqueue获得的每个数据包,它必须决定( 返回判决 )是处理数据包本身(即,就操作系统而言将其丢弃)还是将其传递给常规TCP实现。

I know for a fact that this approach works, but it's cumbersome. 我知道这种方法有效,但这很麻烦。

You can use libpcap, in Python it seems this module: http://pylibpcap.sourceforge.net/ or this one: https://pypi.python.org/pypi/pypcap 您可以使用libpcap,在Python中似乎使用以下模块: http : //pylibpcap.sourceforge.net/或以下模块: https : //pypi.python.org/pypi/pypcap

With pcap you can register to receive messages from the kernel. 使用pcap可以注册以接收来自内核的消息。 By providing the correct filter from your application, you can receive TCP segments from the Kernel. 通过从您的应用程序中提供正确的过滤器,您可以从内核接收TCP段。 I have used libpcap in C and I suppose you can use the indicated modules in the same way. 我在C语言中使用过libpcap,我想您可以以相同的方式使用所示的模块。 For me this is the best solution as you can handle it from the application in a pretty standard way. 对我来说,这是最好的解决方案,因为您可以以标准的方式从应用程序中处理它。

To avoid the kernel responding with a RST, your solution with iptables looks the best one for me. 为了避免内核用RST响应,您的iptables解决方案对我来说是最好的解决方案。

Since you are doing this all yourself with raw packets, why not just create your own MAC address and IP address? 既然您是自己处理原始数据包的,那么为什么不创建自己的MAC地址和IP地址呢? You would need to put the adapter into promiscuous mode to receive packets, but if you do this, the kernel shouldn't send any responses to your incoming packets as they will appear to be addressed to "some other system". 您可能需要将适配器置于混杂模式下以接收数据包,但是如果这样做,内核不应发送任何对传入数据包的响应,因为它们似乎将被寻址到“其他系统”。 This makes it trivial to filter the packets you care about from others. 这使得从其他人过滤您关心的数据包变得轻而易举。

You will also need to respond to ARPs appropriately in order for the other system to find your MAC address. 您还需要适当地响应ARP,以便其他系统找到您的MAC地址。 And if you need DHCP for obtaining an IP address, you would need to handle those interactions as well. 而且,如果您需要DHCP来获取IP地址,则也需要处理这些交互。

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

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