SivaDotRender
SivaDotRender

Reputation: 1651

TCP handshake using python RAW sockets

I am implementing a TCP handshake using python RAW sockets. The Linux kernel is however being quite annoying because it attempts to handle certain aspects of this protocol.

For example, when I send a SYN packet, the server responded with a SYN, ACK packet; to which the kernel automatically responds with a RST packet resetting the connection. I overcame this my dropping all such reset packets using the following iptable rule:

-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. 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. Does anyone know a reasonable workaround?

Upvotes: 4

Views: 2856

Answers (3)

Gil Hamilton
Gil Hamilton

Reputation: 12357

Since you are doing this all yourself with raw packets, why not just create your own MAC address and IP address? 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. And if you need DHCP for obtaining an IP address, you would need to handle those interactions as well.

Upvotes: 1

rodolk
rodolk

Reputation: 5907

You can use libpcap, in Python it seems this module: http://pylibpcap.sourceforge.net/ or this one: https://pypi.python.org/pypi/pypcap

With pcap you can register to receive messages from the kernel. By providing the correct filter from your application, you can receive TCP segments from the Kernel. I have used libpcap in C and I suppose you can use the indicated modules in the same way. 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.

Upvotes: 1

Malt
Malt

Reputation: 30335

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. Nfqueue has existing python bindings, so using it shouldn't be an issue.

The idea is to catch all incoming TCP Syns before they reach the kernel's TCP implementation. Then pass these packets to the nfqueue which your userland app can monitor. 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 (i.e. drop the packet as far as the OS is concerned) or pass it along to the regular TCP implementation.

I know for a fact that this approach works, but it's cumbersome.

Upvotes: 1

Related Questions