IPv6
IPv6 does IPv4's job with 128-bit addresses, so every device can have its own globally reachable address. Its header has a fixed 40-byte size. Options moved out of it into separate extension headers, chained one after the other.
The header
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| Traffic Class | Flow Label |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Payload Length | Next Header | Hop Limit |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ Source Address (128 bits) +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ Destination Address (128 bits) +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 4 bits | Version | 6 |
| 0 | 8 bits | Traffic Class | Priority and ECN, like IPv4's DSCP / ECN. |
| 1 | 20 bits | Flow Label | Marks the packets of one flow, so routers can keep them on the same path. Linux picks it from a hash of the connection. |
| 4 | 2 | Payload Length | Everything after this 40-byte header, extension headers included. |
| 6 | 1 | Next Header | What follows: 6 TCP, 17 UDP, 58 ICMPv6, or an extension header (0 Hop-by-Hop, 43 Routing, 44 Fragment, 60 Destination Options). Same numbers as IPv4's Protocol. |
| 7 | 1 | Hop Limit | IPv4's TTL under its real name. |
| 8 | 16 | Source | |
| 24 | 16 | Destination |
Compared to IPv4, the header has:
- no checksum: the link and transport layers already have one;
- no fragmentation fields: only the sender fragments, with a Fragment extension header;
- no header length: it's always 40 bytes.
Example: a DNS answer over IPv6
0000 00 00 5e 00 53 01 00 00 5e 00 53 02 86 dd 60 05
0010 52 92 00 41 11 40 20 01 0d b8 00 00 00 00 00 00
0020 00 00 00 00 00 02 20 01 0d b8 00 00 00 00 00 00
0030 00 00 00 00 00 01 00 35 d3 41 00 41 5b c7 ...
After the Ethernet header (86 dd = IPv6):
| Bytes | Field | Value |
|---|---|---|
60 05 52 92 |
Version, Traffic Class, Flow Label | 0110 = 6; class 0x00; flow label 0x55292 |
00 41 |
Payload Length | 65 bytes: 8 (UDP) + 57 (DNS) |
11 |
Next Header | 17, UDP |
40 |
Hop Limit | 64 |
20 01 0d b8 00 … 00 02 |
Source | 2001:db8::2 |
20 01 0d b8 00 … 00 01 |
Destination | 2001:db8::1 |
How the first four bytes split, in bits:
6 0 0 5 5 2 9 2
0110 0000 0000 0101 0101 0010 1001 0010
ver traffic cl. flow label: 0x55292
NetOtter's i:
EtherType IPv6 (0x86dd)
Source 2001:db8::2
Destination 2001:db8::1
Next header UDP (17)
Hop limit 64
Flow label 0x55292
Traffic cls 0x00
Writing addresses
128 bits are written as 8 groups of 4 hex digits: 2001:0db8:0000:0000:0000:0000:0000:0002.
- Leading zeros in a group are dropped:
2001:db8:0:0:0:0:0:2. - The longest run of zero groups becomes
::, once per address:2001:db8::2.
Extension headers
Each extension header starts with its own Next Header byte, so they form a chain that ends at the transport protocol:
flowchart LR
ip["IPv6 header<br/>Next Header = 0"] --> hbh["Hop-by-Hop Options<br/>Next Header = 58"] --> icmp["ICMPv6 (MLD report)"]
Example: an MLD report with a Hop-by-Hop header
When an interface comes up, IPv6 tells the local routers which multicast groups it listens to, with an MLD report. That report must carry a Router Alert option, which goes in a Hop-by-Hop header. Here is the client's first packet once its cable was up:
0000 33 33 00 00 00 16 00 00 5e 00 53 01 86 dd 60 00
0010 00 00 00 38 00 01 00 00 00 00 00 00 00 00 00 00
0020 00 00 00 00 00 00 ff 02 00 00 00 00 00 00 00 00
0030 00 00 00 00 00 16 3a 00 05 02 00 00 01 00 8f 00
0040 1a 6e 00 00 00 02 04 00 00 00 ff 02 00 00 00 00
0050 00 00 00 00 00 01 ff 00 53 01 04 00 00 00 ff 02
0060 00 00 00 00 00 00 00 00 00 01 ff 00 00 01
| Bytes | Layer | Meaning |
|---|---|---|
33 33 00 00 00 16 |
Ethernet | IPv6 multicast MAC: 33:33 + the last 4 bytes of ff02::16 |
00 38 00 01 |
IPv6 | payload 56 bytes, Next Header 0 (Hop-by-Hop), hop limit 1 (never routed) |
00 … 00 |
IPv6 | source ::: the interface has no address yet (it's checking its address is unique) |
ff 02 … 00 16 |
IPv6 | destination ff02::16: all MLDv2-capable routers |
3a 00 |
Hop-by-Hop | next header 58 (ICMPv6); length 0 = 8 bytes in all |
05 02 00 00 |
Hop-by-Hop | option 5 (Router Alert), 2 bytes, value 0 = MLD |
01 00 |
Hop-by-Hop | option 1 (PadN), 0 bytes: pads to 8 |
8f 00 1a 6e 00 00 00 02 |
ICMPv6 | type 143 (MLDv2 report), checksum, 2 records |
04 00 00 00 ff 02 … ff 00 53 01 |
MLD record | type 4 (change to exclude: "I join"), group ff02::1:ff00:5301 |
04 00 00 00 ff 02 … ff 00 00 01 |
MLD record | the same, group ff02::1:ff00:1 |
The groups joined are solicited-node addresses: ff02::1:ff + the last 3 bytes of an address of the interface. ff02::1:ff00:5301 is the one of fe80::200:5eff:fe00:5301 (the link-local address, made from the MAC), ff02::1:ff00:1 the one of 2001:db8::1. Neighbour discovery (IPv6's ARP) sends its queries there.
NetOtter follows the chain:
Next header HOPO (0)
Upper layer ICM6 (58), after 8 bytes of extension headers
Hop limit 1
Flow label 0x00000
Traffic cls 0x00
MLD v2 listener report (143)
Group ff02::1:ff00:5301 (solicited-node) change to exclude, 0 sources
Group ff02::1:ff00:1 (solicited-node) change to exclude, 0 sources
Addresses worth knowing
| Prefix | Use |
|---|---|
::1 |
loopback |
:: |
unspecified (no address yet) |
fe80::/10 |
link-local: every interface has one, never routed |
fc00::/7 (in practice fd00::/8) |
unique local, IPv6's private addresses |
2000::/3 |
global unicast |
ff00::/8 |
multicast; ff02::1 all nodes, ff02::2 all routers |
2001:db8::/32 |
documentation (RFC 3849) |
A machine usually has several IPv6 addresses at once: link-local, global, and temporary global addresses that change daily for privacy. NetOtter's me filter remembers all of them.
In NetOtter
- Parsing:
parse_ipv6()(Parsers) reads the fixed header.skip_ipv6_extensions()then walks up to 8 Hop-by-Hop, Routing and Destination Options headers, and stops at a Fragment header. l: addresses in brackets with their port,hopinstead ofttl, and the protocol after the extensions (MLD shows asICM6, with[join …]).- Filters:
ipv6src,ipv6dest,ipv6,proto(which matches Next Header or the upper protocol),etype ipv6.
Read more
User guide
- Overview
- Installation
- Getting started
- Command-line options
- Interactive commands
- Display filters
- Analysis view
- Reverse DNS and privacy
- Anomaly detection
- Save files
- Memory and limits
- Troubleshooting
Developer documentation
- Overview
- Building
- Architecture
- OS backends
- Packet parsing
- Packet storage
- Save format
- Hostname learning
- Reverse DNS internals
- Filters and analysis internals
- Anomaly lab
- Coding conventions
- Function explorer
Learning