Frontend Labs
⋯

Part IV — The Internet Layer (IPv6)

IPv6 is not "IPv4 with more bits." Auto-configuration, the death of NAT and broadcast, mandatory ICMPv6, and a fixed header change day-to-day operations.

16. IPv6 addressing and notation

16.1 The address

128 bits, written as eight groups of four hex digits: 2001:0db8:0000:0000:0000:ff00:0042:8329.

Compression rules:

  1. Drop leading zeros per group: 2001:db8:0:0:0:ff00:42:8329.
  2. Replace one run of all-zero groups with ::: 2001:db8::ff00:42:8329. (Only once — :: twice would be ambiguous.)
  3. Hex is case-insensitive; lowercase is the norm (RFC 5952).

Prefix length is always CIDR: 2001:db8:abcd:12::/64.

16.2 Structure of a typical unicast address

| 48 bits global routing prefix | 16 bits subnet | 64 bits interface ID |
|   2001:0db8:abcd               :  0012          :  0000:0000:0000:0001 |
|<---------- given to you by your ISP/RIR ------->|<-- you pick per host -->|
  • The /64 is sacred: SLAAC, many implementations, and lots of tooling assume every LAN is exactly a /64. Don't subnet longer than /64 for normal LANs.
  • A site typically gets /48 (65 536 subnets) or /56 (256 subnets) from its ISP. A single home often gets a /56 or /60 via DHCPv6-PD (prefix delegation).
  • Interface ID (last 64 bits): historically EUI-64 (derived from the MAC: split it, insert ff:fe, flip the U/L bit) — but that leaks your MAC and lets you be tracked across networks, so modern hosts use RFC 8981 temporary privacy addresses (random, rotated daily) for outbound and often a stable random address for inbound.

16.3 Address types (there is no broadcast)

Prefix Type Notes
::1/128 Loopback equals IPv4 127.0.0.1
::/128 Unspecified "no address yet" (used as source during DAD)
fe80::/10 Link-local Auto-configured on every IPv6 interface, always present, never routed. Used by NDP, OSPFv3, and as next-hop. You must specify the zone: ping6 fe80::1%eth0.
fc00::/7 (fd00::/8 in practice) Unique Local (ULA) The IPv6 "private" range; generate a random /48. Not globally routed.
2000::/3 Global unicast (GUA) Internet-routable.
ff00::/8 Multicast Replaces broadcast. Scoped: ff02::1 all-nodes (link), ff02::2 all-routers, ff02::fb mDNS, ff02::1:ffXX:XXXX solicited-node (used by NDP).
2002::/16 6to4 legacy transition, deprecated
2001:db8::/32 Documentation safe for examples
64:ff9b::/96 NAT64 well-known prefix maps IPv4 into IPv6 (Ch. 18)
::ffff:0:0/96 IPv4-mapped ::ffff:192.0.2.1 — how a dual-stack socket represents an IPv4 peer

An interface normally has several addresses at once: one fe80:: link-local, maybe a ULA, one or more GUAs (stable + temporary). This is normal, not a misconfig.

16.4 The IPv6 header (fixed 40 bytes)

|Version| Traffic Class |           Flow Label                  |
|         Payload Length          | Next Header |   Hop Limit    |
|                     Source Address (128 bits)                  |
|                  Destination Address (128 bits)                |

Differences from IPv4 that matter:

  • No header checksum (link layer + transport checksums suffice; and IPv6 requires the UDP checksum, unlike IPv4).
  • No IHL / options in the base header — extension headers chain via Next Header (Hop-by-Hop, Routing, Fragment, ESP, AH, Destination). Firewalls sometimes drop long extension-header chains.
  • Hop Limit = IPv4's TTL, renamed.
  • Flow Label (20 bits): lets routers ECMP-hash a flow consistently without parsing L4; also used by QUIC.
  • No fragmentation fields — moved to an extension header, source-only.

16.5 War story

An app "worked on IPv4, hung on IPv6" for some users. getaddrinfo returned a AAAA, the app connected to a GUA, but the user's ISP had broken IPv6 (RA present, no working upstream). The app didn't implement Happy Eyeballs (Ch. 18) so it waited a full 75 s connect timeout before trying IPv4. Fix: use a client library with Happy Eyeballs v2, or lower the connect timeout and race both families. Lesson: in a dual-stack world, always race A and AAAA; never let one broken family block the other.

Try it yourself

ip -6 addr show                         # all v6 addresses (note multiple per iface)
ip -6 route
ping6 -c3 2606:4700:4700::1111           # Cloudflare v6
ping6 fe80::1%eth0                        # link-local needs a zone id
sysctl net.ipv6.conf.all.use_tempaddr    # 2 = prefer privacy addresses

Generated from real-life-example.md · 8 Oct 2026 16:36