Tcpdump – Capturing Specific BFD Packets Using Tcpdump

bfdtcpdump

I'm troubleshooting a problem with my site-to-site VPN at one location. I've narrowed it down to the link being up, but traffic dropping due to routing problems. I'm running ospf with over ipsec protected gre tunnels on two Ubiquiti routers.

I'm using tcpdump to try and capture bfd packets with a non-zero diagnostic field. I'm using the BFD header described in RFC 5880 found here

bfd packet header from rfc 5880

Essentially the BFD header field I'm interested in should be bits 3-7 of byte 0 from the BFD header.

I'm running the following tcpdump command:

sudo tcpdump -i tun1001 "port 3784 and ip[9] &255==17" -vvv -s 0

(I realized that I don't need the &255, I was just trying to make sure things worked the way that I understand them) This shows me the packets I'm looking for to start with:

13:21:25.269162 IP (tos 0x0, ttl 255, id 18326, offset 0, flags [DF], proto UDP (17), length 52)
    10.254.254.1.55178 > 10.254.254.2.3784: [no cksum] BFDv1, length: 24
        Control, State Up, Flags: [Control Plane Independent], Diagnostic: No Diagnostic (0x00)
        Detection Timer Multiplier: 3 (750 ms Detection time), BFD Length: 24
        My Discriminator: 0x0000178b, Your Discriminator: 0x0000177d
          Desired min Tx Interval:     250 ms
          Required min Rx Interval:    250 ms
          Required min Echo Interval: 1000 ms

Adding ip[24] &31 == 0 still shows packets, confusingly displaying even packets with a diagnostic field set. I also tried ip[24]&192>>5=1 to get protocol version 1 but that did not behave as expected either.

I've tried adding ((ip[24]&0x1f)!=0) without any luck either. The session drops without showing that packet that I normally see containing ( Diagnostic:Control Detection Time Expired (0x01) ).

I feel like I'm missing something really basic.

Best Answer

Okay, so I found this link which had an interesting example of how to build a tcpdump filter to match SMTP packets beginning with the string 'MAIL' in the segment data.

It looks like my biggest error was in forgetting that the UDP packet nested inside the IP packet is what I wanted to filter. Using that, I came up with

sudo tcpdump -i tun1001 "(udp[2:2]==3784) and ip[9] &255==17 and ((udp[8] &0x1f)>0)" -vvv -s 0 -XX

which seems to do what I want and show packets with diagnostic bits only. The correct filter for the version would then be ( in this filter the diagnostics bits are filtered to be absent ):

 sudo tcpdump -i tun1001 "(udp[2:2]==3784) and ip[9] &255==17 and ((udp[8] &0x1f)=0) and ((udp[8] &0xe0)>>5)==1" -vvv -s 0 -XX