Basic syntax : ============== Filtering hosts : ----------------- - Match any traffic involving 192.168.1.1 as destination or source # tcpdump -i eth1 host 192.168.1.1 - As soure only # tcpdump -i eth1 src host 192.168.1.1 - As destination only # tcpdump -i eth1 dst host 192.168.1.1 Filtering ports : ----------------- - Match any traffic involving port 25 as source or destination # tcpdump -i eth1 port 25 - Source # tcpdump -i eth1 src port 25 - Destination # tcpdump -i eth1 dst port 25 Network filtering : ------------------- # tcpdump -i eth1 net 192.168 # tcpdump -i eth1 src net 192.168 # tcpdump -i eth1 dst net 192.168 Protocol filtering : -------------------- # tcpdump -i eth1 arp # tcpdump -i eth1 ip # tcpdump -i eth1 tcp # tcpdump -i eth1 udp # tcpdump -i eth1 icmp Let's combine expressions : --------------------------- Negation : ! or "not" (without the quotes) Concatanate : && or "and" Alternate : || or "or" - This rule will match any TCP traffic on port 80 (web) with 192.168.1.254 or 192.168.1.200 as destination host # tcpdump -i eth1 '((tcp) and (port 80) and ((dst host 192.168.1.254) or (dst host 192.168.1.200)))' - Will match any ICMP traffic involving the destination with physical/MAC address 00:01:02:03:04:05 # tcpdump -i eth1 '((icmp) and ((ether dst host 00:01:02:03:04:05)))' - Will match any traffic for the destination network 192.168 except destination host 192.168.1.200 # tcpdump -i eth1 '((tcp) and ((dst net 192.168) and (not dst host 192.168.1.200)))'
So tcpdump doesn’t have a GRE pattern matches, but that doesn’t mean you can’t use ip[xx] to inspect things within gre. In a normal GREv0 packet: ip[36:4] is the source IP address, ip[40:4] is the destination and ip[33] is the protocol.
So, to match all TCP packets within a GRE header, write ‘tcpdump ip[33] = 0x06’, or to match anything sent from 127.0.0.1 within GRE, write ‘tcpdump ip[36:4] = 2130706433’ (or tcpdump ip[36] = 127 and ip[37] = 0 and ip[38] = 0 and ip[39] = 1).
Or, on the other hand, just use wireshark.
If you ever debugged network node with GRE you should know that painful feeling of tcpdump output. Thousands IPs and you can not differentiate them, because they are in GRE.
And there is no filters for IP addresses inside GRE. You can not say ‘tcpdump -ni eth0 proto gre and host 192.168.0.1’. Well, you can, but ‘host’ will be used only to filter source or destination of GRE packets, not the incapsulated IP packet.
Unfortunately there is no nice syntax. Fortunately, there is some, at least.
You’ll need to convert IP address to network-byte-ordered integer. For this every octet should be converted to hex and joined together ‘as is’. 100.64.6.7 will become 0x64400607.
For python: there is module ipaddress, but it’s not available in default installation. So we’ll do it manually with minimal code:
>> “0x%x%x%x%x” % tuple(map(int,’192.168.0.1′.split(‘.’)))
‘0xc0a801’
(sorry for mad code, but I wanted to keep it short).
Result of that code is ‘number’ representing IP address (in the example above – 192.168.0.1).
Now we can run tcpdump:
tcpdump -ni eth1 ‘proto gre and (ip[54:4]=0xc0a801 or ip[58:4]=0xc0a801)’
Numbers in the square brackets near ‘ip’ is offset and size of the field. IPv4 address is 4 bytes long. Because GRE add 42 bytes overhead (20 bytes first IP header, 8 bytes GRE header, 14 bytes encapsulated Ethernet header), we taking normal IP source/destination offset (see here) and adding it.
ip[36:4] is the source IP
ip[40:4] is the destination IP
We can verify the incoming traffic to see if they have VLAN
tags by using tcpdump
with the -e and vlan
option.
This will show the details of the VLAN
header:
# tcpdump -i bond0 -nn -e vlan
To capture the issue live.
or
# tcpdump -i eno1 -nn -e vlan -w /tmp/vlan.pcap
To write to the capture to a file.
If tcpdump is unable to filter any traffic, whereas running tcpdump unfiltered does show traffic, then the problem may be due to an extra Ethernet header being added, which is typically a VLAN header: 802.1Q VLAN. Use the tcpdump -e option to see this extra header information, which should look like the following:
. . . ethertype 802.1Q, length 64: vlan 128, p 0, ethertype IPv4,
IP 192.168.128.42.8001 > 192.168.128.90.20700:
Port Filtering
Trying to filter using tcpdump fails. An example is to filter on a known port number, such as the following:
tcpdump -ni eth2 port 8001
If tcpdump is unable to provide a filtered output, then the passive capture software is not able to do so either.
If it is VLAN-type traffic, use the vlan expression operator as part of the filter expression:
tcpdump -ni eth2 vlan and port 8001
Other examples of filtering with VLAN packets:
tcpdump -nr tst.dmp 'ether[12:2] = 0x8100'
tcpdump -nr tst.dmp vlan and ip and port 8001
To show both types of traffic:
tcpdump -nr tst.dmp ip or vlan
HowTo – tell tcpdump to filter mixed tagged and untagged VLAN (IEEE 802.1Q) traffic
A week ago I needed to filter VLAN traffic with tcpdump. Everything went well, as long as *only* tagged or *only* untagged traffic was given as input. However, when trying to filter say UDP packets out of traffic that contains both tagged and untagged packets, tcpdump screwed my filters. As I think this situation may happen to some more people, here some input for nerds struggling with the same issue in the future. Example doomed to fail with mixed traffic:
tcpdump -nn -v udp This simple BPF filter should basically deliver all UDP packets, regardless whether the traffic is tagged with a VLAN tag or not. But: it doesn’t. The issue is that tagging traffic inserts four more bytes (namely the VLAN ID) to the ethernet (or more precisely IEEE 802.1Q) header. Without specifically asking for VLAN traffic in the BPF filter, every traffic is parsed as untagged traffic. Thus, the specified filter delivers only untagged UDP packets (i.e., their frames) and drops all tagged traffic. Now watch out: similar things happen if you specify the mysterious ‘vlan’ keyword in the tcpdump filter. After specifiying the ‘vlan’ keyword, the *subsequent* filters are matched against traffic shifted by 4 bytes to the right. Note that this is also true if you specify ‘not vlan’ as filter. The internals of how tcpdump translates the BPF filter are exposed when calling tcpdump with the -b option: BPF translation of filter ‘not vlan and udp’:
[root@vm-fedora ~]# tcpdump -nn -d not vlan and udp (000) ldh [12] (001) jeq #0x8100 jt 10 jf 2 (002) ldh [16] (003) jeq #0x86dd jt 4 jf 6 (004) ldb [24] (005) jeq #0x11 jt 9 jf 10 (006) jeq #0x800 jt 7 jf 10 (007) ldb [27] (008) jeq #0x11 jt 9 jf 10 (009) ret #96 (010) ret #0 What do we see here? Although we explicitly specified to have untagged traffic, our filter fails and matches UDP traffic that has no VLAN tag but is shifter by 4 byte to the right (i.e., it matches nothing). Our fault was to specify the ‘vlan’ keyword, such that all preceding filters (‘udp’) are matched against shifted traffic. To cope with this issue, one should be careful in which order the filter is put together. If we want to match both tagged and untagged UDP traffic, we have to specify the following filter: Filter UDP traffic, both VLAN tagged and untagged:
[root@vm-fedora ~]# tcpdump -nn -d "udp or (vlan and udp)" Or, the generic solution: Generic filter expression that matches VLAN tagged and untagged traffic:
[root@vm-fedora ~]# tcpdump -nn -d "<filter> or (vlan and <filter>)" If you want to filter only untagged traffic, specify the following: Generic filter to match only untagged traffic:
[root@vm-fedora ~]# tcpdump -nn -d <filter> and not vlan Long story short: When using tcpdump (or libpcap), be careful where to put the ‘vlan’ keyword in your expression. In general, it’s a very bad idea to specify the keyword twice, unless you pack VLAN traffic into VLAN traffic. Maybe these examples are more explanative than the quote below taken from the tcpdump manpage: “Note that the first vlan keyword encountered in expression changes the decoding offsets for the remainder of expression on the assumption that the packet is a VLAN packet.” Recall this (admittedly sometimes strange) behavior is not a bug… Thanks goes to Nuno Paiva, who sent me an example how to solve matching mixed traffic. Thanks to Dan Cox who spotted missing quotes. Thanks to Max Lukoshkov for spotting a language issue (subsequent vs. preceding). |
tcpdump Flags:
TCP Flag tcpdump Flag Meaning SYN S Syn packet, a session establishment request. ACK A Ack packet, acknowledge sender’s data. FIN F Finish flag, indication of termination. RESET R Reset, indication of immediate abort of conn. PUSH P Push, immediate push of data from sender. URGENT U Urgent, takes precedence over other data. NONE A dot . Placeholder, usually used for ACK.