3
votes

I've been using my raspberry pi as a sniffer, and have observed some interesting differences between tcpdump and scapy. I am seeing the following:


Traffic Generator Machine, Linux Box with scapy:

sendp(Ether(dst='ff:ff:ff:ff:ff:ff',src="AA:00:00:00:00:00")/Dot1Q(vlan=10)/IP()/ICMP())


Raspberry Pi, ala 'tcpdump':

00:25:10.156830 aa:00:00:00:00:00 (oui Unknown) > Broadcast, ethertype 802.1Q (0x8100),length 60: vlan 10, p 0, ethertype IPv4, localhost > localhost: ICMP echo request, id 0, seq 0, length 8


Rasperry Pi, via 'scapy':

>>> pkt[0].show()
###[ Ethernet ]###   
    dst= ff:ff:ff:ff:ff:ff   
    src= aa:00:00:00:00:00   
    type= 0x800
###[ IP ]###
       version= 4L
       ihl= 5L
       tos= 0x0
       len=28
       id= 1
       flags= 
       frag= 0L
       ttl= 64
       proto= icmp
       chksum= 0x7cde
       src= 127.0.0.1
       dst= 127.0.0.1
       \options\
###[ ICMP ]###
          type= echo-request
          code= 0
          chksum= 0xf7ff
          id= 0x0
          seq= 0x0
###[ Padding ]###
              load= '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' None

Even when I try:

>>> Dot1Q in pkt[0]
False


Does anyone know why scapy is unable to capture (parse?) the vlan frame, but tcpdump sees it fine ?

(PS I also sniffed with scapy, and exported a pcap file, and then read the pcap file with tcpdump... the vlan tags are gone... disappeared... )

=======================

For those interested, my workaround for now is to use tcpdump to capture to a pcap file, and then use rdpcap() in scapy to load that data, so I can use scapy's powerful parsing features to explore the capture- this introduces a layer of caching, and a nasty system call into my program, but gets me reliable vlan information...

=======================

Based on RyPeck's answer and GuyHarris's advice, I now have a much better workaround:

a) Using http://sourceforge.net/projects/pylibpcap/

import pcap
conf.use_pcap=True

b) Using pcappy - which is can be installed with: pip install pcappy

import pcappy as pcap
conf.use_pcap=True

Now scapy shows the same vlan information as tcpdump, with all it's great parsing features intact!

2

2 Answers

4
votes

Update: support was added in GH2091 and is now available in Scapy 2.4.3+, on Python 3 only

This was recently discussed in the Scapy mailing list here.

As I said and pointed out, earlier, the vlan layer is stripped by the kernel before scapy or tcpdump get it. But tcpdump now has support to add it back. Hence you can create a ticket for scapy to support this enhancement too. - Philippe Biondi (Scapy Inventor)

This explains why the VLAN Layer is disappearing. Nothing to do at this time except get in on a potential feature request/ticket. Feel free to create one over at the Scapy BitBucket.

@GuyHarris offered a different potential solution, that having aforementioned feature in tcpdump will add the support for Scapy, this would apply for you if your Scapy installation is using libpcap to capture packets.

2
votes

I tried to do what you said but it didn't work. 'conf.L2listen 'still used 'PF_PACKETS' instead of libpcap. I started looking into the code and found that 'conf.use_pcap' is processed only in the 'pcapdnet' module. That means that if you don't import it, 'conf.use_pcap' is discarded and 'conf.L2listen' remains 'PF_PACKETS' instead of changing to 'L2pcapListenSocket' (which is the socket that binds to libpcap).

the solution is simple:

conf.use_pcap = True
import scapy.arch.pcapdnet 

make sure that the you import the module AFTER you change the configuration, otherwise it won't work. you can check that it worked if you look at:

conf.L2listen

and the value is:

 <L2pcapListenSocket: read packets at layer 2 using libpcap>

it didn't work if the value is:

<L2ListenSocket: read packets at layer 2 using Linux PF_PACKET sockets>