DEV Community

IPYE
IPYE

Posted on AI-assisted

tcpdump and Wireshark Filters for IPv6: Practical Recipes and the Extension Header Caveat

Disclosure up front: I run IPYE, a company that leases IP space. It gets one short paragraph at the end; the rest is plain networking.

When an IPv6 problem is not obvious from logs, a packet capture usually settles it: is the Router Advertisement arriving, is the Neighbor Solicitation answered, does the handshake complete, is something sending ICMPv6 errors? The IPv6 filter syntax has a few differences from IPv4 that cause silent mistakes. This article gives recipes for tcpdump (which uses the libpcap filter language) and for Wireshark display filters, and explains the limitation that catches most people. Examples use 2001:db8:100::25, 2001:db8:100::/48, and eth0.

Two different filter languages

Both tools have filters, and they are not the same:

  • A capture filter (tcpdump's expression, or Wireshark's capture filter box) uses BPF syntax and decides what is recorded at all.
  • A display filter (Wireshark) works on dissected packets and decides what is shown from a capture.

Capture filters are efficient but crude. Display filters are expressive but need the packets to have been captured first. A typical workflow is a broad capture filter, then a display filter in Wireshark to narrow things down. Quote tcpdump expressions in the shell, because (, ), and ! have meaning there.

Basic tcpdump options

tcpdump -n -i eth0 -vv 'ip6'
Enter fullscreen mode Exit fullscreen mode
  • -n stops name resolution, which avoids delays and extra DNS queries that pollute the capture.
  • -i any captures on all interfaces; it uses a different link-layer header, but ip6 filters still work.
  • -vv prints more detail, including hop limit.
  • -w file.pcap writes a capture file for Wireshark.

Addresses and prefixes

host 2001:db8:100::25
src host 2001:db8:100::25
net 2001:db8:100::/48
ip6 and not host 2001:db8:100::25
Enter fullscreen mode Exit fullscreen mode

host matches either direction, net takes a prefix, and the ip6 primitive restricts the filter to IPv6.

Protocols and ports

tcp port 443, udp port 53, and icmp6 all work for IPv6. icmp6 is a shorthand for IPv6 packets with next header 58. Port filters apply to both IPv4 and IPv6 unless you add ip6 or ip, so write ip6 and tcp port 443 when you want IPv6 only.

The extension header caveat

This is the limitation that matters. In libpcap's filter language, ip6 proto 6 and similar expressions look only at the Next Header field in the fixed IPv6 header. If a packet has a Hop-by-Hop, Routing, or Fragment extension header, the next header is that extension, so a filter for TCP will not match it. Similarly, filters for ports or ICMPv6 types read at fixed offsets and assume the upper-layer header follows the 40-byte fixed header immediately. For ordinary traffic this works. For packets with extension headers it can silently miss. When a capture seems to be missing traffic you know exists, widen the filter, or capture everything for a short period and filter in Wireshark, whose dissector follows the extension header chain.

There is also a primitive for chains: ip6 protochain 44 matches packets that have a Fragment header anywhere in the chain.

ICMPv6 and neighbor discovery

The ICMPv6 type is the first byte after the 40-byte header, so with the no-extension-header assumption you can match it at offset 40:

Goal Filter
Router Solicitation (type 133) icmp6 and ip6[40] == 133
Router Advertisement (134) icmp6 and ip6[40] == 134
Neighbor Solicitation (135) icmp6 and ip6[40] == 135
Neighbor Advertisement (136) icmp6 and ip6[40] == 136
All neighbor discovery (133 to 136) icmp6 and ip6[40] >= 133 and ip6[40] <= 136
Packet Too Big (type 2) icmp6 and ip6[40] == 2
Echo request and reply (128, 129) icmp6 and (ip6[40] == 128 or ip6[40] == 129)

Neighbor discovery messages must be sent with a hop limit of 255, and receivers reject anything else, which stops off-link senders from spoofing them. The hop limit is the byte at offset 7, so icmp6 and ip6[7] == 255 and ip6[40] >= 133 and ip6[40] <= 136 shows only well-formed discovery packets, and a capture with ip6[7] != 255 on the same types shows suspicious ones. For multicast, ip6 multicast matches any IPv6 multicast destination.

Useful checks with these:

  1. Is SLAAC working? Capture type 134 on a client interface. If none arrive, the problem is upstream of the host: router, switch, or MLD snooping.
  2. Is a neighbour answering? Capture types 135 and 136 for the target address and look for the advertisement.
  3. Path MTU trouble? Capture type 2 to see whether Packet Too Big reaches the sender. Absence in the face of black-holed large packets suggests filtering, as described in the earlier MTU and ICMPv6 articles.

TCP handshake and flags

For a SYN on IPv6 without extension headers, the TCP flags byte is at offset 53 (40 plus 13 in the TCP header):

ip6 and tcp and (ip6[53] & 0x02 != 0)
Enter fullscreen mode Exit fullscreen mode

Behaviour of protocol-relative expressions such as tcp[13] with IPv6 has varied between libpcap versions, so the explicit offset is more predictable, and you should verify any filter against known traffic first.

Fragments

ip6 protochain 44 matches fragmented packets. IPv6 fragmentation is done only by the source, so fragments you see came from the endpoint or from a tunnel entry point, and a flow of fragments often points to an MTU problem.

Wireshark display filters

Display filters use field names:

  • ipv6.addr == 2001:db8:100::25, ipv6.src, and ipv6.dst for addresses.
  • icmpv6 for all ICMPv6, and icmpv6.type == 135 for a specific type.
  • ipv6.hlim == 255 or ipv6.hlim < 64 for hop limit.
  • ipv6.nxt == 44 for packets whose fixed header points to a fragment header.
  • tcp.flags.syn == 1 && tcp.flags.ack == 0 for new connections, regardless of address family.
  • ipv6 && !icmpv6 to remove ICMPv6 noise while looking at application traffic.

Summary

Use capture filters to limit what you record and display filters to explore it. Remember that libpcap IPv6 offsets assume no extension headers, check the hop limit of 255 for neighbor discovery, and test a new filter against traffic you know exists before trusting an empty result.

About IPYE

IPYE (https://my.ipye.com) leases IPv4, IPv6, and ASN space; a /48 IPv6 block is free for the first year. LOA, ROA, rDNS, and WHOIS are handled by IPYE. Locations: Los Angeles, New York, Ashburn, Salt Lake City, London, Amsterdam, and Frankfurt. Questions: ipye@turnel.com.

Disclosure: I run IPYE

Top comments (0)