Filtering GRE enacpsulated packets with tcpdump

I can ask tcpdump to show me GRE encapsulated packets quite simply with tcpdump -ni any proto gre:

15:02:57.209082 IP 10.14.0.3 > 10.14.0.2: GREv0, key=0x1, length 106: IP 10.10.10.11 > 10.10.10.1: ICMP echo request, id 21073, seq 2784, length 64
15:02:57.209138 IP 10.14.0.2 > 10.14.0.3: GREv0, key=0x1, length 106: IP 10.10.10.1 > 10.10.10.11: ICMP echo reply, id 21073, seq 2784, length 64
15:02:57.345098 IP 10.14.0.2 > 10.14.0.3: GREv0, key=0x1, length 74: IP 169.254.192.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 1, prio 50, authtype none, intvl 2s, length 20

But is it possible to filter for example only encapsulated icmp packets, or any other arbitrary expression?


Solution 1:

Since this was of use to me, updating this answer.

If you want to look at a proto inside of another proto, you can't just use proto in the match.

protochain works like proto, however it specifically changes the offset for the next match for this exact purpose.

Instead use:

protochain GRE && proto ICMP

Source: pcap-filter(7)

Solution 2:

In case your tcpdump version does not support protochain like the one in Debian 8 for example, you can manually calculate the position, where the protocol number of the ip packet within the GRE tunnel is determined.

ICMP has protocol number 0x01. And it is stored in the 10th byte of the packet. GREv0 has 24 bytes, plus nine (because one counts from zero) equals 33:

tcpdump -i any proto 47 and ip[33]=0x01