Reputation: 1651
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
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
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
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