How filter only keep-alive packet with tcpdump

A keepalive probe is a packet with no data in it and the ACK flag turned on

port="port_number_being_used"
intf="name_of_the_network_interface"
tcpdump -pni ${intf} -v "tcp port ${port} and ( tcp[tcpflags] & tcp-ack != 0 and ( (ip[2:2] - ((ip[0]&0xf)<<2) ) - ((tcp[12]&0xf0)>>2) ) == 0 ) "

what this does:

  • bit-wise and between tcp flags field and tcp-ack to make sure it is an ACK
  • The IP packet length (in bytes) - The IP header length - The TCP Header Length to make sure it has no data

Disclaimer: not actually tested, but should point you in a good direction

NOTE: breakdown of the tcpdump filter to make it more readable. probably can take out the first set of parens.

tcp port ${port}
and
(
 tcp[tcpflags] & tcp-ack != 0
 and
 (
  (ip[2:2] - ((ip[0] & 0xf) << 2))
  -
  ((tcp[12] & 0xf0) >> 2)
 ) == 0
)

Wireshark uses the same capture syntax as tcpdump. Both work from libpcap. However, I think the feature you are looking at in Wireshark is a display filter which heuristically analyzes neighboring packets. I think the best you can do at capture is to look for 1-byte or 0-byte ACKs in response to a keep-alive request. Try this;

tcpdump -vv "tcp[tcpflags] == tcp-ack and less 1"

and see if you get traffic between the expected hosts.

RFC 1122 covers TCP Keep-alives and leaves much of the implementation up to the vendor.


Also, you could consider using tcpdump on your Linux host to capture to a file and then transfer the capture to your workstation for analysis.