Sniffing TCP Packets With Python

Inspired by this StackOverflow question, “How do I sniff on a port for log messages using python?”, I decided to figure out how to capture and process packets in Python. It turns out to be quite easy once you work out the kinks. Except the kinks were a pain to determine.

Sample output:

It may appear that the same packets are printed twice here, but what you’re really seeing is the same packet going out and then coming back in. The timestamps give it away. Also, if you have an OSX version of tcpdump, the -k ID option will print something like this: (lo0, out) .

Basic, high-level usage:

And then the actual generator:

Depending on the interface you capture from, you may receive Ethernet, Loopback, or IP packets. This means that a little deduction must be done to determine how to decode them. We figure this out once, and save the decoding function for all future packets. Although, if you never need to enter promiscuous mode1, you use the “iptap” interface and you will only ever receive IP packets.

All of the decode functions return either data or None if a parsing error occurs. Here’s the one for Ethernet packets:

As a bonus, here’s a couple of methods that print out binary data similar to the hexdump -C command, but without the trailing ASCII.

With debugging turned on, the output is much more verbose:

  1. Ethernet interfaces normally filter out any network traffic not destined for the current machine. Setting the interface to be promiscuous, tells it to pass through all packets it receives.