Why echo request doesn't show in tcpdump?

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.

Is there a chance that the replies are going out on a different interface (perhaps one for IPSec?) from the one (eth0) that you are running tcpdump on?