3
votes

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?

3
Would you consider using Scapy? github.com/secdev/scapyJohn Zwinck
Is scapy able to revive and parse the SYN, ACK ? By belief was that this packet was dropped by the KernelSivaDotRender
I don't know, I suggested it as a possible higher-level library you can use (or at least learn from), vs. trying to do it all yourself from scratch.John Zwinck
@JohnZwinck I verified what scapy was doing. It appears as though it implements a packet capture method, similar to what rodolk suggested belowSivaDotRender

3 Answers

1
votes

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.

1
votes

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.

1
votes

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.