IPipv6notationcompressionglobal unicastlink-local

IPv6: Not Just Bigger Addresses

IPv6 gives every device a globally routable address and removes NAT as a necessity — but it also redesigns the header, replaces ARP and broadcast with ICMPv6 multicast, lets hosts configure themselves from router advertisements, forbids router fragmentation, and coexists with IPv4 through dual-stack and Happy Eyeballs rather than replacing it.

IPv6
▶ InteractiveInterview question
Progress

The problem

IPv4 ran out, and NAT kept it alive at the price of breaking end-to-end reachability. A replacement needs vastly more addresses — but if the designers were going to touch the header anyway, what else about IPv4 was worth fixing while nobody could stop them?

What IPv6 actually changes

The headline is 128-bit addresses: 3.4 × 10^38 of them, enough to give every device on Earth a public address with a /64 subnet to spare — and that is the real point, not the count. With every host publicly addressable, NAT is no longer necessary: a phone can accept a connection from a laptop, two peers can talk without a relay, and "server" becomes something any device can be. Firewalls still decide what is *allowed*; they no longer have to fake reachability.

The rest of the redesign is easy to miss. The header is a fixed 40 bytes with no checksum and no options — options moved to chained extension headers — so routers parse it faster. Broadcast is gone; everything that used it is multicast, and multicast is mandatory. ARP is gone, replaced by Neighbor Discovery over ICMPv6 (see ARP and Neighbor Discovery: From an IP to a Local MAC). Routers never fragment. Hosts can configure their own addresses from a router advertisement without DHCP (SLAAC). Every interface has several addresses at once, by design. A flow label lets routers hash a flow without reading the transport header. "IPv4 with longer addresses" describes none of this.

  • 128-bit addresses; a /64 per subnet is the norm; a home gets a /56 or /48.
  • No NAT needed; no broadcast; no ARP; no router fragmentation; no header checksum; no options in the base header.
  • Neighbor Discovery, SLAAC, mandatory multicast and temporary privacy addresses are part of the protocol, not add-ons.

Notation and compression

An IPv6 address is eight groups of 16 bits in hexadecimal, separated by colons: 2001:0db8:0000:0000:0000:0000:0000:0001. Two rules shorten it. Leading zeros in a group may be dropped: 0db8db8, 00000. One run of consecutive all-zero groups may be replaced by `::` — only one, or the address would be ambiguous; if there are two runs, compress the longer (the leftmost if equal). The result is 2001:db8::1. Reverse it by counting groups: 2001:db8::1 has two on the left and one on the right, so :: stands for five zero groups.

Because colons are also used for ports, an address with a port is written in brackets: [2001:db8::1]:443, and that is what URLs use — https://[2001:db8::1]/. Prefixes use CIDR as in IPv4: 2001:db8::/32 is a documentation range (the IPv6 counterpart of 192.0.2.0/24), 2001:db8:1::/64 is one subnet. The lowercase hex form with :: compression is the canonical text representation (RFC 5952); comparing addresses as strings without canonicalising them is a classic bug.

Compressing 2001:0db8:0000:0000:0000:ff00:0042:8329
full        2001:0db8:0000:0000:0000:ff00:0042:8329
drop zeros  2001:db8:0:0:0:ff00:42:8329
one ::      2001:db8::ff00:42:8329          ← the run of three zero groups
with port   [2001:db8::ff00:42:8329]:443

::1         loopback (all zeros except the last bit)
::          unspecified (all zeros) — "any" when binding
fe80::1     a link-local address
2001:db8::/32   documentation prefix — never on the real internet

Address types and scopes

IPv6 addresses carry their scope in their prefix, and a host holds several at once. Global unicast (currently 2000::/3, so anything starting with 2 or 3) is the public, routable kind — your 2001:… or 2a02:… address. Link-local (fe80::/10) is automatically configured on every interface, valid only on that segment, never routed; Neighbor Discovery and router advertisements use it, and a default route in IPv6 usually points at the router’s link-local address, not its global one. Unique local (fc00::/7, in practice fd00::/8 with a random 40-bit suffix) is the private range — routable inside an organisation, not on the internet — but unlike RFC 1918 it is meant to be globally unique by randomness, so merging two networks does not collide. Multicast (ff00::/8) carries a 4-bit scope: ff02::1 is all nodes on the link, ff02::2 all routers, ff02::1:ffxx:xxxx the solicited-node group. There is no broadcast.

Because the address is so large, the interface identifier — the low 64 bits — can be anything unique on the link. It was once derived from the MAC (EUI-64: split the MAC, insert ff:fe, flip a bit), which leaked hardware identity and let a laptop be tracked across networks; modern stacks generate a stable random identifier per network (RFC 7217) and additionally rotate temporary addresses (RFC 8981) for outgoing connections every day or so. A typical interface therefore shows a link-local, a stable global, and one or more temporary global addresses at the same time.

IPv6 address types
PrefixTypeScopeRouted?Analogue
2000::/3global unicastinternetyespublic IPv4
fe80::/10link-localone segmentnever169.254/16, but always present and essential
fc00::/7 (fd00::/8)unique localorganisationinternally onlyRFC 1918, but globally unique by randomness
ff00::/8multicast (scoped)per addressper scope224/4; also replaces broadcast
::1/128loopbackhostno127.0.0.1
::/128unspecifiedno0.0.0.0
::ffff:a.b.c.dIPv4-mappedAPI onlynolets a v6 socket accept v4 clients
2001:db8::/32documentationno192.0.2.0/24

Finding neighbours and configuring yourself

A host that comes up on an IPv6 link builds its link-local address from the prefix fe80:: and an interface identifier, verifies it is unused with duplicate address detection (a neighbor solicitation for itself), and then sends a router solicitation to ff02::2. A router answers with a router advertisement listing the on-link prefix (2001:db8:1::/64), the link MTU, its own lifetime as a default gateway, and flags saying whether to use SLAAC, DHCPv6 for addresses, or DHCPv6 only for extras such as DNS servers (RAs can also carry DNS servers directly, RFC 8106). With SLAAC the host appends its identifier to the prefix and has a global address within a second of link-up, with no server and no lease.

Address resolution — the ARP replacement — is a neighbor solicitation to the target’s solicited-node multicast group and a neighbor advertisement back, cached with reachability states in ip -6 neigh. The whole family is ICMPv6, which means a firewall that drops ICMPv6 does not merely break ping6: it prevents a host from finding its router, its neighbours, or its own address. Allow at least types 133–137 (RS, RA, NS, NA, Redirect) and 2 (Packet Too Big) on every IPv6 network.

Living with both: dual-stack and Happy Eyeballs

Browser

IPv6 is not backward compatible on the wire — an IPv6 packet is EtherType 0x86DD and an IPv4-only router will not forward it — so the transition is dual-stack: hosts and networks run both protocols side by side, every service publishes both A and AAAA records, and each connection picks one. Around 45–50% of Google’s traffic arrives over IPv6 today; mobile carriers are often IPv6-only internally with NAT64/DNS64 translating to reach the IPv4 internet, and some clouds now charge for IPv4 while IPv6 is free.

Picking one is the browser’s job. A naive "try IPv6, and if it times out try IPv4" would stall for a full connect timeout (tens of seconds) whenever the IPv6 path is broken — and it often is, silently, on networks that advertise a prefix but do not route it. Happy Eyeballs (RFC 8305) races them: resolve both, start the IPv6 connection first, and if it has not completed within about 250 ms start the IPv4 one too; use whichever completes first and close the other. The result is that a broken IPv6 path costs a quarter of a second, not a failure — and that "this site is slow to start loading" on a misconfigured network is often exactly that quarter-second. curl -6 and curl -4 force a family when you need to test one path in isolation.

Servers see the consequence too: on a dual-stack service, a single client can appear from an IPv6 address and, moments later, an IPv4 one; rate limits, sessions and allowlists keyed on the client address must treat both. And an IPv6 client behind no NAT presents its real, stable-per-network address — a privacy and a logging difference from the IPv4 world where one address was a whole household.

Key points

  • IPv6 exists because IPv4 ran out — but its design goal was restoring end-to-end reachability: every device gets a public address and NAT stops being necessary.
  • Notation: eight hex groups; drop leading zeros; replace one run of zero groups with ::; bracket the address when adding a port.
  • Types by prefix: global unicast 2000::/3, link-local fe80::/10 (always present, never routed), unique local fd00::/8, multicast ff00::/8. No broadcast.
  • ARP is replaced by Neighbor Discovery over ICMPv6; routers advertise prefixes and hosts configure themselves (SLAAC). Filtering ICMPv6 breaks all of it.
  • Fixed 40-byte header, no checksum, no router fragmentation, extension headers for options, several addresses per interface, temporary addresses for privacy.
  • Transition is dual-stack; Happy Eyeballs races v6 and v4 with a ~250 ms head start so a broken v6 path costs a quarter-second, not a timeout.

Why does this exist?

Mechanisms are answers to constraints. Open each question before reading the answer.

Why 128 bits and not 64?

So that addressing never needs to be conserved again: a /64 per link allows stateless autoconfiguration with a 64-bit random identifier and no collision management, and there are still 2^64 links. The design spends bits to buy simplicity.

Why remove broadcast?

Broadcast wakes every host on a segment for every request; scoped multicast with computed group addresses (solicited-node) reaches only the interested hosts. The efficiency matters on large and battery-powered segments.

Why is adoption taking decades?

IPv6 gives no benefit to a site until the other side has it too, and NAT made IPv4 adequate for the client–server web. The economics only turned when public IPv4 addresses acquired a price and mobile carriers found IPv6-only cheaper to run.

Why does the default route point at a link-local address?

Router advertisements are sent from the router’s link-local address, and it is the one address a router is guaranteed to have on that link regardless of how global prefixes change. It also means renumbering a site does not touch host routes.

IPv6 notation

IPv6 notation
Eight 16-bit hex groups. Compression is cosmetic; the bits are the same.
IPv6
type
global unicast 2000::/3
64-bit prefix (network)
2001:0db8:0000:0000::/64
64-bit interface identifier
0000:ff00:0042:8329
20010db8000000000000ff0000428329
Internet-routable. Typically a /48 per site, /64 per subnet, no NAT.
Dual-stack: Happy Eyeballs (RFC 8305)
  1. 1. Resolver sends AAAA and A queries in parallel.
  2. 2. AAAA answer: 2001:db8::1 (12 ms). A answer: 93.184.216.34 (14 ms).
  3. 3. Start the IPv6 connection first (preferred); arm a ~250 ms fallback timer.
  4. 4. IPv6 SYN-ACK arrives at 40 ms → IPv6 wins, IPv4 never attempted.
  5. 5. Connection established over IPv6. The user saw no delay.
1/5 · Happy Eyeballs

How it fails

What the failure looks like from inside real software.

  • Broken IPv6 path with valid AAAA records: every site takes ~250 ms longer to start; curl -6 hangs, curl -4 works. Fix the network or disable the AAAA.
  • ICMPv6 filtered "for security": hosts lose their default route when the RA lifetime expires; connectivity dies minutes after boot and returns after a reboot.
  • Rogue router advertisement from a VM or a misconfigured laptop: every host on the segment routes IPv6 through it; Windows Internet Connection Sharing is a classic source.
  • Rate limiting keyed on the address: an IPv6 client rotates temporary addresses and evades a per-address limit; a /64 per subscriber is the sensible key.
  • String comparison of addresses: 2001:db8::1 and 2001:0db8:0:0:0:0:0:1 are the same address and fail an equality check; canonicalise (RFC 5952) first.
  • A server bound to 0.0.0.0 only: IPv4 clients connect, IPv6 clients get connection refused; bind :: (dual-stack socket) or both.