IPv6 Addressing Explained
IPv4 served the internet for decades, but its 32-bit address space — roughly 4.3 billion addresses — ran out. IANA exhausted the last blocks in 2011. The long-term answer is IPv6, which uses 128-bit addresses and provides approximately 340 undecillion (3.4 × 10³⁸) unique addresses — enough to assign billions of addresses to every grain of sand on Earth.
Beyond sheer quantity, IPv6 brings architectural improvements: built-in autoconfiguration, mandatory IPsec support, simplified headers for faster routing, and the elimination of NAT for most use cases. As a Linux administrator you will increasingly encounter IPv6 in cloud environments, ISP allocations, and modern data centres, so understanding it thoroughly is essential.
Why IPv6?
| Problem with IPv4 | IPv6 Solution |
|---|---|
| 4.3 billion addresses — exhausted | 340 undecillion addresses |
| NAT required for private networks | Every device can have a globally routable address |
| Manual or DHCP-only configuration | Stateless autoconfiguration (SLAAC) built in |
| Optional IPsec | IPsec support mandatory in the specification |
| Complex header with many fields | Simplified fixed-length header (40 bytes) |
| Broadcast traffic | No broadcast — uses multicast instead |
| Fragmentation by routers | Only source hosts fragment; routers do not |
Address Structure
An IPv6 address is 128 bits long, written as eight groups of four hexadecimal digits separated by colons:
1
2001:0db8:85a3:0000:0000:8a2e:0370:7334
Each group (called a hextet or quartet) represents 16 bits. Hexadecimal uses digits 0–9 and letters a–f, so each hex digit represents 4 bits.
1
2
3
4
Full address:
2001 : 0db8 : 85a3 : 0000 : 0000 : 8a2e : 0370 : 7334
16b 16b 16b 16b 16b 16b 16b 16b
= 128 bits total
Hex to Binary Mapping
| Hex | Binary | Hex | Binary |
|---|---|---|---|
| 0 | 0000 | 8 | 1000 |
| 1 | 0001 | 9 | 1001 |
| 2 | 0010 | a | 1010 |
| 3 | 0011 | b | 1011 |
| 4 | 0100 | c | 1100 |
| 5 | 0101 | d | 1101 |
| 6 | 0110 | e | 1110 |
| 7 | 0111 | f | 1111 |
Address Notation Rules
Writing 32 hex characters with colons is verbose. Two abbreviation rules keep addresses manageable.
Rule 1: Omit Leading Zeros Within a Group
Each group of four hex digits can drop its leading zeros:
1
2
2001:0db8:0000:0042 → 2001:db8:0:42
^^^^ ^^^^ ^^^^
Note that 0000 becomes 0 (not empty — at least one digit must remain).
Rule 2: Replace One Run of Consecutive All-Zero Groups with ::
The double-colon :: can replace one or more consecutive groups of all zeros, but only once per address (using it twice would make the address ambiguous):
1
2
3
4
5
6
7
8
9
10
11
2001:0db8:0000:0000:0000:0000:0000:0001
→ 2001:db8::1
fe80:0000:0000:0000:0204:61ff:fe9d:f156
→ fe80::204:61ff:fe9d:f156
0000:0000:0000:0000:0000:0000:0000:0001
→ ::1 (loopback)
0000:0000:0000:0000:0000:0000:0000:0000
→ :: (unspecified)
Expanding a Compressed Address
To expand :: back to full form, count the existing groups, then fill in enough 0000 groups to make eight total:
1
2
3
4
5
2001:db8::1
Groups present: 2001, db8, 1 → 3 groups
Groups needed: 8 − 3 = 5 zero groups inserted at ::
Full: 2001:0db8:0000:0000:0000:0000:0000:0001
Tip: When in doubt, expand the address to all 8 groups before analysing it. The
python3 -c "import ipaddress; print(ipaddress.ip_address('2001:db8::1').exploded)"one-liner does this instantly on any Linux system.
Address Anatomy: Prefix and Interface ID
Like IPv4’s network/host split, an IPv6 address has two parts:
1
2
3
| ← Prefix (network portion) → | ← Interface ID (host portion) → |
2001:0db8:85a3:0001 : 0000:0000:abcd:1234
←————— 64 bits ——————→ ←————— 64 bits ——————→
The standard allocation for end-user networks is a /64 prefix, leaving 64 bits for the interface identifier. This means a single /64 subnet has 2⁶⁴ ≈ 18.4 quintillion addresses — far more than any subnet will ever need.
ISPs typically assign:
-
/48to organisations (65,536 possible /64 subnets) -
/56to home users (256 possible /64 subnets) -
/64to individual links
1
2
3
4
5
6
Organisation gets: 2001:db8:abcd::/48
←— 48-bit prefix —→
Can create subnets: 2001:db8:abcd:0001::/64
2001:db8:abcd:0002::/64
...
2001:db8:abcd:ffff::/64 (65,536 subnets)
Address Types
IPv6 has three fundamental address types — broadcast no longer exists.
Unicast
A unicast address identifies one specific interface. Traffic sent to a unicast address is delivered to exactly one destination.
Global Unicast (GUA) — routable on the public internet. Always starts with 2 or 3 in the first hex digit (prefix 2000::/3):
1
2
2001:db8:1:1::10/64
2600:1400:d:5a4::17de
Link-Local — automatically assigned to every IPv6-enabled interface. Only valid within a single network segment (not routed). Always starts with fe80::/10:
1
2
fe80::1%eth0
fe80::204:61ff:fe9d:f156
The %eth0 suffix (called a zone ID or scope ID) is required when using link-local addresses in commands because the same fe80:: prefix appears on every interface — the zone ID tells the OS which one to use.
Unique Local Address (ULA) — the IPv6 equivalent of RFC 1918 private space. Not routed on the public internet. Starts with fc00::/7 (in practice almost always fd00::/8):
1
fd12:3456:789a:1::1/64
Loopback — always ::1/128. Equivalent to IPv4’s 127.0.0.1:
1
::1
Unspecified — :: (all zeros). Used as a source address before an address is assigned, or to mean “any address” in a server bind context. Equivalent to IPv4’s 0.0.0.0.
Multicast
A multicast address identifies a group of interfaces. Traffic is delivered to all members of the group. Always starts with ff:
| Address | Group | Scope |
|---|---|---|
ff02::1 |
All nodes | Link-local |
ff02::2 |
All routers | Link-local |
ff02::fb |
mDNS | Link-local |
ff02::1:2 |
All DHCP agents | Link-local |
ff05::2 |
All routers | Site-local |
IPv6 uses multicast where IPv4 used broadcast. For example, a router discovery request goes to ff02::2 (all routers on the link) rather than a broadcast address.
Anycast
An anycast address is assigned to multiple interfaces (typically on different routers). Traffic is delivered to the nearest one according to the routing protocol. Anycast addresses look identical to unicast addresses — the difference is in how they are assigned and advertised.
Prefix Notation and Subnetting
IPv6 uses the same CIDR /n notation as IPv4.
1
2
3
4
2001:db8::/32 — a /32 prefix (e.g. assigned to an ISP)
2001:db8:1::/48 — a /48 prefix (e.g. assigned to an organisation)
2001:db8:1:a::/64 — a /64 prefix (a single subnet)
::1/128 — a /128 host route (one specific interface)
Subnet Planning Example
Organisation receives 2001:db8:acad::/48. Plan subnets for four departments:
The 48-bit prefix leaves 16 bits for subnetting (bits 49–64) before the 64-bit interface ID begins. That gives 2¹⁶ = 65,536 possible /64 subnets.
| Department | Subnet | Prefix |
|---|---|---|
| HQ | 2001:db8:acad:0001::/64 |
Subnet 1 |
| Engineering | 2001:db8:acad:0002::/64 |
Subnet 2 |
| Sales | 2001:db8:acad:0003::/64 |
Subnet 3 |
| DMZ | 2001:db8:acad:0100::/64 |
Subnet 256 |
Each /64 subnet accommodates 2⁶⁴ − 2 ≈ 18.4 quintillion hosts. In practice, only the /128 host route and the subnet-router anycast address (all interface ID bits = 0) are special — there is no broadcast address to subtract.
Interface ID Generation
The 64-bit interface ID can be generated in several ways:
EUI-64 (Extended Unique Identifier)
Derived automatically from the interface’s 48-bit MAC address:
- Split the MAC in half and insert
ff:fein the middle - Flip bit 7 (the Universal/Local bit) of the first byte
1
2
3
4
5
6
7
MAC: 00:1a:2b:3c:4d:5e
Split: 00:1a:2b | 3c:4d:5e
Insert: 00:1a:2b:ff:fe:3c:4d:5e
Flip bit 7: 02:1a:2b:ff:fe:3c:4d:5e
Interface ID: 021a:2bff:fe3c:4d5e
Full address: fe80::21a:2bff:fe3c:4d5e
Privacy concern: EUI-64 embeds the MAC address in the IPv6 address, making a device trackable across networks. RFC 4941 Privacy Extensions generate a random, temporary interface ID instead and rotate it periodically. Most modern operating systems enable privacy extensions by default.
RFC 4941 Privacy Extensions (Random)
The OS generates a random 64-bit interface ID and replaces it periodically (typically every 24 hours for temporary addresses). This is the default on Linux, Windows, and macOS for outbound connections.
Manually Configured
You assign the interface ID explicitly — useful for servers and routers where a predictable, stable address is required:
1
2001:db8:1:1::10/64 ← ::10 is the manually chosen interface ID
Autoconfiguration: SLAAC and DHCPv6
IPv6 devices can configure themselves without any manual intervention.
SLAAC (Stateless Address Autoconfiguration — RFC 4862)
The most common method on LANs:
- The interface generates a link-local address (
fe80::/10+ interface ID) at startup. - It sends a Neighbour Solicitation to verify no other device uses that address (DAD — Duplicate Address Detection).
- It sends a Router Solicitation (
ff02::2) asking for network information. - A router responds with a Router Advertisement containing the network prefix (e.g.
2001:db8:1::/64), default gateway, and flags. - The device combines the advertised prefix with its interface ID to form a global unicast address.
- It sends another DAD for the new GUA.
No DHCP server is needed. The router advertisement alone is sufficient to fully configure the interface.
DHCPv6 (Stateful)
Works like DHCPv4 — a DHCPv6 server leases specific addresses and provides additional options (DNS servers, domain names). The router advertisement sets flags to tell clients whether to use SLAAC, DHCPv6, or both:
| RA Flag | Meaning |
|---|---|
M=0, O=0 |
SLAAC only — no DHCPv6 |
M=0, O=1 |
SLAAC for address + DHCPv6 for options (DNS, etc.) |
M=1, O=1 |
Full DHCPv6 — address and options from server |
Stateless DHCPv6
A common hybrid: SLAAC assigns the address, DHCPv6 provides only DNS server information (M=0, O=1). Many ISPs and enterprise networks use this model.
NDP: Neighbour Discovery Protocol
NDP (RFC 4861) replaces IPv4’s ARP. It uses ICMPv6 messages over multicast to perform address resolution, router discovery, and duplicate address detection.
| ICMPv6 Type | Message | Purpose |
|---|---|---|
| 133 | Router Solicitation (RS) | Host asks routers to send RA |
| 134 | Router Advertisement (RA) | Router announces prefix, gateway, flags |
| 135 | Neighbour Solicitation (NS) | Equivalent to ARP request |
| 136 | Neighbour Advertisement (NA) | Equivalent to ARP reply |
| 137 | Redirect | Router tells host of a better next-hop |
Solicited-Node Multicast Address
Instead of broadcasting like ARP, NDP sends Neighbour Solicitations to a solicited-node multicast address derived from the target’s address:
1
2
3
4
5
Prefix: ff02::1:ff00:0/104
Last 24 bits: taken from the target address
Target: 2001:db8::abcd:1234
Solicited-node: ff02::1:ffcd:1234
Only the device(s) whose address ends in cd:1234 listen on that multicast group — far more efficient than ARP’s link-layer broadcast.
Dual-Stack Operation
During the IPv4-to-IPv6 transition, most production systems run dual-stack — both protocols active simultaneously on the same interface. The OS chooses which to use based on the destination address and application preferences.
1
2
3
4
5
# A dual-stack interface shows both addresses
ip addr show eth0
# inet 192.168.1.100/24 brd 192.168.1.255 scope global eth0
# inet6 2001:db8:1::100/64 scope global
# inet6 fe80::1%eth0/64 scope link
Address selection preference (RFC 6724): IPv6 global unicast is preferred over IPv4 when both are available. Applications that explicitly bind to 0.0.0.0 (IPv4 only) will not use IPv6 even on a dual-stack system.
Configuring IPv6 on Linux
View Addresses and Routes
1
2
3
4
ip -6 addr show # IPv6 addresses only
ip addr show eth0 # All addresses on eth0
ip -6 route show # IPv6 routing table
ip -6 neigh show # NDP neighbour cache (equivalent to ARP table)
Assign a Static Address (Temporary)
1
2
sudo ip -6 addr add 2001:db8:1::100/64 dev eth0
sudo ip -6 route add default via 2001:db8:1::1
Persistent Configuration (Netplan — Ubuntu 18.04+)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# /etc/netplan/01-netcfg.yaml
network:
version: 2
ethernets:
eth0:
addresses:
- 192.168.1.100/24 # IPv4 static
- 2001:db8:1::100/64 # IPv6 static
routes:
- to: default
via: 192.168.1.1
- to: ::/0
via: 2001:db8:1::1
nameservers:
addresses:
- 8.8.8.8
- 2001:4860:4860::8888 # Google DNS over IPv6
1
sudo netplan apply
Persistent Configuration (nmcli — RHEL/CentOS)
1
2
3
4
5
sudo nmcli con mod eth0 ipv6.addresses "2001:db8:1::100/64"
sudo nmcli con mod eth0 ipv6.gateway "2001:db8:1::1"
sudo nmcli con mod eth0 ipv6.dns "2001:4860:4860::8888"
sudo nmcli con mod eth0 ipv6.method manual
sudo nmcli con up eth0
Enable/Disable SLAAC
1
2
3
4
5
6
7
8
9
# Check if SLAAC is active (accept_ra = 1 means yes)
cat /proc/sys/net/ipv6/conf/eth0/accept_ra
# Disable SLAAC on an interface (use static only)
sudo sysctl -w net.ipv6.conf.eth0.accept_ra=0
# Make persistent
echo "net.ipv6.conf.eth0.accept_ra=0" | sudo tee -a /etc/sysctl.d/99-ipv6.conf
sudo sysctl -p /etc/sysctl.d/99-ipv6.conf
Enable IPv6 Forwarding (Router/Gateway)
1
2
3
4
sudo sysctl -w net.ipv6.conf.all.forwarding=1
# Persistent
echo "net.ipv6.conf.all.forwarding=1" | sudo tee -a /etc/sysctl.d/99-ipv6.conf
Diagnostic Commands
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Test connectivity
ping6 ::1 # Loopback test
ping6 fe80::1%eth0 # Link-local (zone ID required)
ping6 2001:4860:4860::8888 # Google DNS (public IPv6)
ping6 -c 4 ipv6.google.com
# Trace route
traceroute6 2001:4860:4860::8888
tracepath6 ipv6.google.com
# DNS — query AAAA record (IPv6)
dig AAAA google.com
nslookup -type=AAAA google.com
# Show NDP neighbour cache
ip -6 neigh show
# Show listening IPv6 sockets
ss -tlnp6
# Check which address the OS selects for a destination
ip -6 route get 2001:4860:4860::8888
Common Issues and Solutions
| Problem | Cause | Solution |
|---|---|---|
| No global unicast address | Router not sending RA | Check router config; radvd on Linux routers |
ping6 fails to link-local |
Missing zone ID | Add %ifname: ping6 fe80::1%eth0
|
| Duplicate address detected (DAD failure) | Address conflict | Change interface ID; check for duplicate static assignments |
| IPv6 disabled on interface | Kernel parameter | sysctl -w net.ipv6.conf.eth0.disable_ipv6=0 |
| Application only listening on IPv4 | Bound to 0.0.0.0
|
Bind to :: (listens on both IPv4 and IPv6 on dual-stack) |
| Slow connections (Happy Eyeballs) | DNS returns AAAA but IPv6 path broken | Fix IPv6 routing or disable IPv6 on the interface |
| Cannot reach link-local address | No zone ID specified | Always include %interface for link-local addresses |
IPv4 vs IPv6 Side-by-Side
| Feature | IPv4 | IPv6 |
|---|---|---|
| Address length | 32 bits | 128 bits |
| Notation | Dotted decimal | Colon-hexadecimal |
| Total addresses | ~4.3 billion | ~3.4 × 10³⁸ |
| Header size | 20–60 bytes (variable) | 40 bytes (fixed) |
| Broadcast | Yes | No (multicast replaces it) |
| Address config | Manual / DHCP | SLAAC / DHCPv6 / manual |
| Fragmentation | Routers and hosts | Source hosts only |
| ARP | Yes | No (NDP replaces it) |
| NAT | Required for private → public | Not required |
| IPsec | Optional | Mandatory in spec |
| Loopback | 127.0.0.1 |
::1 |
| Private range | RFC 1918 | ULA fc00::/7
|
| Link-local |
169.254.x.x APIPA |
fe80::/10 (always present) |
| Multicast | 224.0.0.0/4 |
ff00::/8 |
Quick Reference
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Address length: 128 bits (8 groups × 16 bits, hex, colon-separated)
Abbreviation: Drop leading zeros; :: for one consecutive run of all-zero groups
Standard prefix: /64 for end-user subnets
Address types:
::1/128 Loopback
::/128 Unspecified
fe80::/10 Link-local unicast (always present, not routed)
fc00::/7 (fd::/8) Unique local (ULA — private, not routed)
2000::/3 Global unicast (internet routable)
ff00::/8 Multicast
Key multicast groups:
ff02::1 All nodes (link-local)
ff02::2 All routers (link-local)
NDP replaces ARP:
RS (133) / RA (134) — router discovery
NS (135) / NA (136) — neighbour resolution
Linux commands:
ip -6 addr show
ip -6 route show
ip -6 neigh show
ping6 <address>%<iface>
traceroute6 <address>
dig AAAA <hostname>
Conclusion
IPv6 is no longer a future technology — it is the present. Major cloud providers, ISPs, and content networks are fully dual-stack, and many mobile networks run IPv6-only. The address structure, notation rules, and autoconfiguration mechanisms covered here give you the foundation to configure interfaces, design subnets, and troubleshoot connectivity on any modern Linux system.
The single most important habit to develop: always include the zone ID (%interface) when working with link-local addresses, and always prefer /64 prefixes for end-user subnets to keep SLAAC and EUI-64 working correctly. With those two rules in mind, IPv6 administration follows naturally from the IPv4 skills you already have.
Additional Resources
- RFC 8200 — IPv6 Specification
- RFC 4291 — IPv6 Addressing Architecture
- RFC 4862 — SLAAC
- RFC 4861 — NDP
- RFC 4941 — Privacy Extensions
- IPv6 Subnet Calculator
- Test Your IPv6 Connectivity
- Linux
ipCommand Reference