TCPDump – Why Echo Request Doesn’t Show in TCPDump?

pingtcpdump

I have two network segments connected using a IPSEC-VPN tunnel :

  • NET#1: a.b.0.0/16 with LAN gateway a.b.0.1
  • NET#2: x.y.0.0/16 with LAN gateway x.y.130.1

I initiate a ping from a.b.0.1 to x.y.130.100 and started a tcpdump. This later shows echo replies packets but it doesn't show echo request packets.

Is it normal? How can I get the echo request packets too?

Here is a sample tests session:

The PING:

# ping x.y.130.100
PING x.y.130.100 56(84) bytes of data.
64 bytes from x.y.130.100: icmp_seq=1 ttl=63 time=1.87 ms
64 bytes from x.y.130.100: icmp_seq=2 ttl=63 time=1.38 ms
64 bytes from x.y.130.100: icmp_seq=3 ttl=63 time=1.27 ms
64 bytes from x.y.130.100: icmp_seq=4 ttl=63 time=3.93 ms
64 bytes from x.y.130.100: icmp_seq=5 ttl=63 time=1.15 ms
64 bytes from x.y.130.100: icmp_seq=6 ttl=63 time=1.16 ms

The TCPDUMP:

# tcpdump -nn 'icmp and (src a.b.0.1 or dst a.b.0.1)'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
13:54:27.607103 IP x.y.130.100 > a.b.0.1: ICMP echo reply, id 22607, seq 1, length 64
13:54:28.608433 IP x.y.130.100 > a.b.0.1: ICMP echo reply, id 22607, seq 2, length 64
13:54:29.610167 IP x.y.130.100 > a.b.0.1: ICMP echo reply, id 22607, seq 3, length 64
13:54:30.614716 IP x.y.130.100 > a.b.0.1: ICMP echo reply, id 22607, seq 4, length 64
13:54:31.613417 IP x.y.130.100 > a.b.0.1: ICMP echo reply, id 22607, seq 5, length 64
13:54:32.615054 IP x.y.130.100 > a.b.0.1: ICMP echo reply, id 22607, seq 6, length 64

Best Answer

This answer assumes Linux as OS.

The output cannot be captured as plaintext by tcpdump: it's already encrypted before tcpdump has a chance to see it and its icmp filter will not match. The input, which arrives encrypted is looped back as plaintext payload: tcpdump captures both, but its icmp filter will match on the second passage.

The Packet flow in Netfilter and General Networking gives clues about this (you'll have to click for details):

Packet flow in Netfilter and General Networking

on the right side (output):

  • plaintext packet reaches xfrm lookup and is looped back as encrypted payload through xfrm encode

  • tcpdump captures later the final result at AF_PACKET. This doesn't match ICMP, nothing will be displayed by the filter

on the left side (input):

  • the encrypted payload arrives and is captured at AF_PACKET by tcpdump: this doesn't match an ICMP and won't be displayed
  • the packet reaches xfrm/socket lookup and undergoes decoding through xfrm decode
  • the now decoded plaintext payload is specifically sent through AF_PACKET: this time tcpdump will see an ICMP packet
  • the plaintext payload follows the now usual routing

Actually in some cases (when IPSec compression is enabled and the packet is a short packet) there can be yet-an-other loop with the intermediate internal packet as ipip protocol.

If you want to get the outgoing traffic, here are some suggestions:

  • you'll have to add something like or esp, but of course it won't be decoded, unless a proper -E option with the adequate secrets is set (which I wouldn't know much about). I don't know if tcpdump can also decode NAT-T (udp port 4500) this way.
  • use iptables or nftables to duplicate packets to a dummy interface. tcpdump can capture on this interface instead.
  • use iptables or nftables to log entire packets to the nflog facility. tcpdump can capture on this pseudo-interface instead.
Related Topic