The Linux Socket Filter: Sniffing Bytes over the Network
Even if the BPF language is pretty simple and easy to learn, most of us would probably be more comfortable with filters written in human-readable expressions. So, instead of presenting the details and instructions of the BPF language (which you can find in the above-mentioned paper), we will discuss how to obtain the code for a working filter starting from a logic expression.
First, you will need to install the tcpdump program from LBL (see Resources). But, if you are reading this article, it is likely that you already know and use tcpdump. The first versions were written by the same people who wrote the BPF paper and its first implementation. In fact, tcpdump uses BPF, in the form of a library called libpcap, to capture and filter packets. The library is an OS-independent wrapper for the BPF engine. When used on Linux machines, BPF functions are carried out by the Linux packet filter.
One of the most useful functions provided by the libpcap is pcap_compile(), which takes a string containing a logic expression as input and outputs the BPF filter code. tcpdump uses this function to translate the command-line expression passed by the user into a working BPF filter. What is interesting for our purposes is that tcpdump has a seldomly used switch, -d, which prints the code of the filter.
For example, typing tcpdump host 192.168.9.10 will start sniffing and grab only those packets whose source or destination IP address matches 192.168.9.10. Typing tcpdump -d host 192.168.9.10 will print the BPF code that recognizes the filter, as shown in Listing 3.
Let's briefly comment on this code; lines 0-1 and 6-7 verify that the captured frame is actually transporting IP, ARP or RARP protocols by comparing their protocol IDs (see /usr/include/linux/if_ether.h) with the value found at offset 12 in the frame (see Figure 1). If the test fails, the packet is discarded (line 13).
Lines 2-5 and 8-11 compare the source and destination IP addresses with 192.168.9.10. Note that, depending on the protocol, the offsets of these addresses are different; if the protocol is IP, they are 26 and 30, otherwise they are 28 and 38. If one of the addresses matches, the packet is accepted by the filter, and the first 68 bytes are passed to the application (line 12).
The filter code is not always optimized, since it is generated for a generic BPF machine and not tailored to the specific architecture that runs the filter engine. In the particular case of the LPF, the filter is run by the PF_PACKET processing routines, which may have already checked the Ethernet protocol. This depends on the protocol field you specified in the initial socket() call: if it is not ETH_P_ALL (which means that every Ethernet frame shall be captured), then only frames having the specified Ethernet protocol will arrive at the filter. For example, in the case of an ETH_P_IP socket, we could rewrite a faster and more compact filter as follows:
(000) ld [26] (001) jeq #0xc0a8090a jt 4 jf 2 (002) ld [30] (003) jeq #0xc0a8090a jt 4 jf 5 (004) ret #68 (005) ret #0
Installing an LPF is a straightforward operation: all you have to do is create a sock_filter structure containing the filter and attach it to an open socket.
The filter structure is easily obtained by substituting the -d switch to tcpdump with -dd. The filter will be printed as a C array that you can copy and paste into your code, as shown in Listing 4. Afterward, you attach the filter to the socket by simply issuing a setsockopt() call.
We will conclude this article with a complete example (see Listing 5 at ftp://ftp.linuxjournal.com/pub/lj/listings/issue86/). It is exactly like the first two examples, with the addition of the LSF code and the setsockopt() call. The filter has been configured to select only UDP packets, having either source or destination IP address 192.168.9.10 and source UDP port equal to 5000.
In order to test this listing, you will need a simple way to generate arbitrary UDP packets (such as sendip or apsend, found on http://freshmeat.net/). Also, you may want to adapt the IP address to match the ones used in your own LAN. To accomplish this, just substitute 0xc0a8090a in the filter code with the IP address of your choice in hex notation.
A final remark concerns the status of the Ethernet card when you exit the program. Since we did not reset the Ethernet flags, the card will remain in promiscuous mode. To solve this problem, all you need to do is install a Control-C (SIGINT) signal handler that resets the Ethernet flags to their previous value (which you will have saved just before ORing with IFF_PROMISC) before exiting the program.
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Dynamic DNS—an Object Lesson in Problem Solving | May 21, 2013 |
| Using Salt Stack and Vagrant for Drupal Development | May 20, 2013 |
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
- RSS Feeds
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Using Salt Stack and Vagrant for Drupal Development
- Dynamic DNS—an Object Lesson in Problem Solving
- New Products
- Validate an E-Mail Address with PHP, the Right Way
- Drupal Is a Framework: Why Everyone Needs to Understand This
- A Topic for Discussion - Open Source Feature-Richness?
- Download the Free Red Hat White Paper "Using an Open Source Framework to Catch the Bad Guy"
- Tech Tip: Really Simple HTTP Server with Python
- Roll your own dynamic dns
2 hours 44 min ago - Please correct the URL for Salt Stack's web site
5 hours 55 min ago - Android is Linux -- why no better inter-operation
8 hours 11 min ago - Connecting Android device to desktop Linux via USB
8 hours 39 min ago - Find new cell phone and tablet pc
9 hours 37 min ago - Epistle
11 hours 6 min ago - Automatically updating Guest Additions
12 hours 15 min ago - I like your topic on android
13 hours 1 min ago - This is the easiest tutorial
19 hours 37 min ago - Ahh, the Koolaid.
1 day 1 hour ago
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?




Comments
only sniff or discard too
hi,
nice article. i like the simplicity of it. However, I am wondering whether this technique can be used to create firewalls ? can i discard packets based on the criteria that I choose. Libpcap won't help because it creates a copy of the packet so the packet does reach where it is intended.
thanks
In both listing1 and
In both listing1 and listing2 when i run them i only see "reply" packets, the "request" packets are ignored..
for example:
i run in a console:
zxc@zxc-l:~$ ping -c1 192.168.1.1
while in another was running:
zxc@zxc-l:~$ sudo ./listing2 (or listing1 it's the same output)
----------
98 bytes read
Source MAC address: 00:af:bc:xx:xx:xx
Destination MAC address: 00:1a:2b:xx:xx:xx
Source host 192.168.1.1
Dest host 192.168.1.213
Source,Dest ports 0,10327
Layer-4 protocol 1
----------
However if i do the same with tcpdump, i get this:
zxc@zxc-l:~$ sudo tcpdump -i eth1 -ntUl
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
IP 192.168.1.213 > 192.168.1.1: ICMP echo request, id 44322, seq 1, length 64
IP 192.168.1.1 > 192.168.1.213: ICMP echo reply, id 44322, seq 1, length 64
In one word, with your examples i can only see reply packets, in fact always my output is:
Dest host 192.168.1.213 (my computers ip).
So my question is, if there is a way to "sniff" both reply packets and also request packets over the network...
Hoping to receive answer...
Thank you very much....
Question...
Hi Gianluca
Excelent article!. I'm writting from Venezuela, and I wanted to know how do I sniff packets without using the PF_PACKET family. I ask you this because I need to do that without root permissions. Thanks
Great work !
Really great tutorial !
I also found video tutorials on sniffing at www.security-freak.net . started by a Vivek Ramachandran, they are quite elaborate in coverage and literally spoon feed topics like sniffing, packet injection etc.
Might help ...take a look !
Some changed in list of include files
Without changes for last C programm compillator gives
warning: implicit declaration of function ‘htons’
If this code changed for C++ programm
(replace exit(X) on return X ) the compiller giver error:
‘htons’ was not declared in this scope
So to improve code include files list might be as follow:
#include
#include
#include
#include
// add this header
#include
#include
#include
#include
// changed #include on
#include
#include
#include
#include
#include
Andy
some problem with formating
#include < stdio.h >
#include < string.h >
#include < errno.h >
#include < unistd.h >
// add this header
#include < asm/types.h >
#include < sys/socket.h >
#include < sys/types.h >
#include < netinet/in.h >
// changed #include < linux/in.h > on
#include < netinet/in.h >
#include < linux/if_ether.h >
#include < net/if.h >
#include < linux/filter.h >
#include < sys/ioctl.h >
Setting promiscuous mode
Great article!
I'd just like to point out that you should not use ioctl() for setting the promiscuous mode. If you do, you're responsible for disabling the promiscuous mode after you're done. Unfortunately, you have no way of knowing if another socket also requested the promiscuous mode while your code was running. Thus, resetting the Ethernet flags to the original value could mess things up.
Instead, you should use setsockopt() with SOL_PACKET, PACKET_ADD_MEMBERSHIP and have PACKET_MR_PROMISC as the argument. This way the kernel will track the promiscuous mode usage and turn it off automatically.
Thanks for the simple way of explanation
Your article made concept so simple. Thanks
thanx
hi,
your document "sniffing bytes over network" is very nice, you have written very clearly so, that we can uderstand. i am a student of master in networking, doing project on filters.
thanking you for your good, nice,and easy to understand document
Regards,
Juxs
Hi Dude....Thu purush naji
Hi Dude....
Thu purush nahi ho.... Maha purush ho..... Sniff sniff sniff and do the right thing for vx180.... Good luck
Re: Kernel Korner: The Linux Socket Filter: Sniffing Bytes over
thanks much for this informative article on a poorly documented subject. this tied together a lot of the bits and pieces i've been sifting through. i'd advise anyone seeking to learn more about creating your own filters to keep this article + source in one hand and the Van Jacobsen/McCanne paper in the other. - britney_spears@hotpop.com
Sniffing Bytes over the Serial port
ACtually i m bit new with the socket programming stuff..Actually wat i want to read the bytes from the socket using read () subroutine (I am using Fedora Envionment)but when i exc the program; it stops at the same position where i defined the read sub routine and does not giving me anything..could u plz comment on this..thx in advance.
Thanx a lot for your
Thanx a lot for your informative article.