THE ADDRESS EXHAUSTION PROBLEM AND THE IPv6 SOLUTION
IPv4 Address Exhaustion
MOTIVATIONIPv4 uses 32-bit addresses — providing a theoretical maximum of 2³² = 4,294,967,296 (about 4.3 billion) unique addresses. When IPv4 was designed in 1981, this seemed enormous. But the explosive growth of the internet — billions of smartphones, IoT devices, cloud servers, home routers — consumed this space far faster than anticipated.
IANA (the global IP address authority) exhausted its IPv4 pool on 3 February 2011. Regional registries ran out of free allocations between 2011–2019. Today, obtaining new public IPv4 addresses requires buying them on the secondary market at premium prices.
Several stopgap measures delayed the crisis:
- CIDR — replaced wasteful classful allocation, made address usage more efficient
- RFC 1918 private addresses + NAT — allowed millions of devices to share a single public IP. A home router with one public IP can serve 100+ internal devices. This is why your home network uses
192.168.x.x - CGN (Carrier-Grade NAT) — ISPs now put entire neighbourhoods behind a single public IPv4 address
NAT solved the exhaustion problem temporarily, but at a cost: it breaks end-to-end connectivity, complicates application protocols (FTP, SIP, WebRTC need ALGs to work through NAT), and adds latency. IPv6 eliminates NAT by giving every device a globally unique address.
IPv6 — The Long-Term Solution
SOLUTIONIPv6 (Internet Protocol version 6) was standardised in RFC 2460 (1998), updated by RFC 8200 (2017). It solves address exhaustion and simultaneously redesigns several IPv4 pain points:
What IPv6 Fixes
- 128-bit addresses — 2¹²⁸ ≈ 3.4 × 10³⁸ unique addresses. Enough to give every atom on Earth its own IP address
- No broadcast — IPv4 broadcast is replaced with targeted multicast, reducing noise on large networks
- Built-in security — IPsec support is mandatory in the specification (optional in IPv4)
- Simplified header — fixed 40-byte header, no checksum, no fragmentation in transit, cleaner extension header chain
- Stateless autoconfiguration (SLAAC) — devices can configure their own addresses without a DHCP server
- No NAT required — every device gets a globally routable address
IPv6 Adoption Today
- Google reports ~45% of global traffic over IPv6 (2024)
- Mobile networks (Jio, T-Mobile, AT&T) are predominantly IPv6-only internally
- All major cloud providers (AWS, GCP, Azure) fully support IPv6
- Most modern OSes (Linux, Windows, macOS, Android, iOS) prefer IPv6 when available
- For NGFW development, IPv6 support is not optional — your firewall must handle both
IPv4 is like a city with 4.3 billion street addresses that is now completely full — every address is taken. To fit more people, residents are crammed into apartment buildings (NAT) where many people share one address and are distinguished by their apartment number (port). IPv6 is like being given an entirely new planet with 340 undecillion addresses — so vast that every grain of sand on Earth gets its own unique address, with quintillions to spare. No apartments needed: every person (device) gets their own unique address.
IPv6 HEADER — 40 BYTES FIXED, SIMPLER THAN IPv4
IPv6 Header Layout
HEADER FORMATThe IPv6 header is always exactly 40 bytes — fixed, no options, no IHL field. This simplicity is intentional: routers can process it faster because they always know exactly where the header ends. IPv4 options (rare but requiring variable-length parsing) are replaced by a clean extension header chain.
Every Field Explained
FIELD REFERENCEVersion (4 bits) = 0110 = 6
Always 6 for IPv6. Receivers check this first to know which IP version to process. Same position as IPv4's Version field — allows a parser to distinguish v4 from v6 without any other context.
Traffic Class (8 bits)
Equivalent to IPv4's DSCP/TOS field. The upper 6 bits are DSCP for QoS marking; the lower 2 bits are ECN. Same semantics as IPv4 — allows routers to prioritise packets based on service class. Your NGFW policy engine uses this for QoS marking.
Flow Label (20 bits) — NEW in IPv6
A 20-bit value identifying a specific flow (sequence of packets from the same source to the same destination, e.g., a single TCP connection or video stream). Routers can use it for fast-path flow-based forwarding without inspecting the full address pair on every packet. This is particularly valuable for ECMP (Equal-Cost Multi-Path) load balancing — all packets of the same flow get the same hash → same path → in-order delivery.
For your DPDK/VPP work: the Flow Label is used in RSS (Receive Side Scaling) hash computation to distribute flows across worker threads.
Payload Length (16 bits)
Length of everything after the 40-byte fixed header — extension headers + upper-layer data. Unlike IPv4's Total Length (which included the header), Payload Length excludes the fixed header. Maximum: 65,535 bytes. For Jumbograms (packets >65,535 bytes), this is set to 0 and a Jumbo Payload option in an extension header carries the actual length.
Next Header (8 bits) — Replaces IPv4 Protocol field
Identifies what follows the fixed IPv6 header. Uses the same protocol number values as IPv4's Protocol field, plus new values for extension headers:
6— TCP (directly follows)17— UDP (directly follows)58— ICMPv6 (directly follows)43— Routing extension header follows44— Fragment extension header follows0— Hop-by-Hop Options header follows59— No next header (empty payload)50— ESP (IPsec, directly follows)
Extension headers form a chain: each extension header has its own Next Header field pointing to the next. The last in the chain points to the actual L4 protocol (TCP=6, UDP=17).
Hop Limit (8 bits) — IPv4's TTL, renamed
Same semantics as IPv4 TTL: decremented by 1 at each router hop, packet discarded when it reaches 0. Renamed "Hop Limit" because it is now accurately named — it was never a time limit, always a hop count.
Source and Destination Addresses (128 bits each = 16 bytes each)
The IPv6 addresses. At 16 bytes each, they dominate the header — 32 of the 40 bytes are just addresses. This is the cost of the larger address space.
Extension Headers — Replacing IPv4 Options
EXTENSION HEADERSIPv4 had an Options field in the main header — complex, variable-length, required all routers to check it. IPv6 replaces this with a cleaner chain of extension headers that most routers skip entirely (only the destination processes most of them):
| Extension Header | Next Header Value | Purpose | Processed by |
|---|---|---|---|
| Hop-by-Hop Options | 0 | Options every router must read (rare — e.g., Router Alert for RSVP) | Every router |
| Destination Options | 60 | Options for the destination host only | Destination only |
| Routing Header | 43 | Loose/strict source routing — list of intermediate nodes | Each listed node |
| Fragment Header | 44 | Fragmentation info (IPv6 only fragments at source) | Destination only |
| Auth Header (AH) | 51 | IPsec authentication | Destination only |
| ESP Header | 50 | IPsec encryption | Destination only |
💡 Key difference from IPv4: In IPv6, routers do not fragment packets. If a packet is too large for a link, the router drops it and sends ICMPv6 "Packet Too Big" (Type 2) back to the source. Only the source can fragment, using the Fragment extension header. This puts fragmentation complexity at endpoints where it belongs, keeping routers fast.
IPv6 ADDRESS FORMAT — 128 BITS, 8 GROUPS OF 16 BITS
IPv6 Address Notation
FORMATAn IPv6 address is 128 bits written as 8 groups of 4 hexadecimal digits, separated by colons. Each group represents 16 bits (2 bytes):
Abbreviation Rules (RFC 5952)
IPv6 addresses are long — two abbreviation rules make them manageable:
Rule 1 — Drop leading zeros within each group:
0db8→db80000→00001→1
Rule 2 — Replace longest consecutive run of all-zero groups with :: (only once per address):
/* Full notation */ 2001:0db8:85a3:0000:0000:8a2e:0370:7334 /* Step 1: Drop leading zeros in each group */ 2001:db8:85a3:0:0:8a2e:370:7334 /* Step 2: Compress the run of zeros (0:0) with :: */ 2001:db8:85a3::8a2e:370:7334 ← final compressed form /* More examples */ fe80:0000:0000:0000:0204:61ff:fe9d:f156 → fe80::204:61ff:fe9d:f156 # 4 consecutive zero groups compressed 0000:0000:0000:0000:0000:0000:0000:0001 → ::1 # loopback address 0000:0000:0000:0000:0000:0000:0000:0000 → :: # unspecified address /* :: can only be used ONCE per address */ 2001:db8::1:0:0:1 # valid — one :: compresses middle zeros 2001::db8::1 # INVALID — two :: is ambiguous /* Prefix notation — same as IPv4 CIDR */ 2001:db8::/32 # network prefix /32 bits fe80::/10 # link-local prefix 2001:db8::1/128 # single host (/128 = one address)
IPv6 in C — Structures and Functions
CODE#include <arpa/inet.h> #include <netinet/in.h> #include <string.h> /* IPv6 address structure: 16 bytes = 128 bits */ struct in6_addr addr; /* Parse a string into binary */ inet_pton(AF_INET6, "2001:db8::1", &addr); /* Print binary as string */ char buf[INET6_ADDRSTRLEN]; /* 46 bytes: enough for any IPv6 string */ inet_ntop(AF_INET6, &addr, buf, sizeof(buf)); printf("%s\n", buf); /* prints: 2001:db8::1 */ /* Access raw bytes (useful for masking) */ uint8_t *bytes = addr.s6_addr; /* 16-byte array */ printf("First byte: %02x\n", bytes[0]); /* Check if address is in a prefix (e.g., fe80::/10 link-local) */ int is_link_local(struct in6_addr *a) { /* fe80::/10 — first 10 bits = 1111 1110 10 */ return (a->s6_addr[0] == 0xfe) && ((a->s6_addr[1] & 0xc0) == 0x80); } /* sockaddr for IPv6 connections */ struct sockaddr_in6 sa6 = {0}; sa6.sin6_family = AF_INET6; sa6.sin6_port = htons(80); inet_pton(AF_INET6, "2001:db8::1", &sa6.sin6_addr); connect(sock, (struct sockaddr *)&sa6, sizeof(sa6));
IPv6 ADDRESS TYPES — NO BROADCAST, THREE MAIN TYPES
Three Address Types — Unicast, Multicast, Anycast
OVERVIEWIPv6 eliminates broadcast entirely. The three address types are:
- Unicast — one sender to one specific receiver. The majority of IPv6 traffic.
- Multicast — one sender to a group of receivers (all addresses starting
FF). Replaces broadcast for all use cases. - Anycast — one sender to the nearest of multiple receivers sharing the same address. Used for DNS root servers, CDN edge nodes.
There is no broadcast in IPv6. What used to be broadcast (e.g., ARP requests) is now done with targeted multicast (NDP Solicited-Node multicast). This is one of the most important architectural improvements.
Unicast Address Types — Know Each One
UNICAST| Type | Prefix | Example | Scope | Use |
|---|---|---|---|---|
| Global Unicast (GUA) | 2000::/3 | 2001:db8::1 | Internet-wide | Publicly routable addresses — the IPv6 equivalent of public IPv4 |
| Link-Local | fe80::/10 | fe80::1 | Single link only | Automatically configured on every IPv6 interface. Used for NDP, router discovery. Never routed beyond a single link. |
| Unique Local (ULA) | fc00::/7 (usually fd00::/8) | fd00::1 | Organisation-wide | IPv6's equivalent of RFC 1918 private addresses. Not routable on internet. Used for internal networks. |
| Loopback | ::1/128 | ::1 | Host-local | Equivalent to 127.0.0.1. Used for local host communication. |
| Unspecified | ::/128 | :: | N/A | Equivalent to 0.0.0.0. Used before address assignment. |
| IPv4-Mapped | ::ffff:0:0/96 | ::ffff:192.0.2.1 | N/A | Represents an IPv4 address in IPv6 notation. Used by dual-stack APIs. |
Global Unicast Address Structure
A GUA is divided into three parts:
/* Global Unicast Address: 2001:db8:1234:5678:abcd:ef01:2345:6789 */ |←── Global Routing Prefix ──→|←─ Subnet ID ─→|←───── Interface ID ─────→| 2001 : 0db8 : 1234 : 5678 : abcd : ef01 : 2345 : 6789 (assigned by ISP/RIR) (you define) (interface-specific) typically 48 bits 16 bits 64 bits /* The /64 boundary is the standard interface prefix */ /* Network: 2001:db8:1234:5678::/64 */ /* Host: anything in the lower 64 bits */
💡 Why /64 everywhere? The 64-bit interface ID boundary is standard in IPv6 for several reasons: SLAAC (address autoconfiguration) uses a 64-bit EUI-64 derived from the MAC address as the interface ID; NDP Solicited-Node multicast uses the lower 24 bits of the interface ID; and /64 subnets give enough space that you'll never run out of host addresses within a subnet.
Multicast Addresses — Replacing Broadcast
MULTICASTAll IPv6 multicast addresses start with FF. The second byte encodes the lifetime (permanent vs transient) and scope (how far the multicast travels):
| Address | Name | Replaces (IPv4) | Used by |
|---|---|---|---|
ff02::1 | All-nodes (link-local) | 255.255.255.255 broadcast | General link-local broadcast equivalent |
ff02::2 | All-routers (link-local) | 224.0.0.2 | Router discovery, DHCPv6 relay |
ff02::5 | OSPFv3 All-routers | 224.0.0.5 | OSPFv3 hello packets |
ff02::6 | OSPFv3 DR/BDR | 224.0.0.6 | OSPFv3 DR/BDR |
ff02::1:ff00:0/104 | Solicited-Node Multicast | ARP broadcast | NDP — neighbour address resolution |
ff05::2 | All-routers (site-local) | N/A | Router discovery across site |
Solicited-Node Multicast — The ARP Replacement
This is how IPv6 avoids broadcast for address resolution. Each interface automatically joins a Solicited-Node multicast group derived from its own IPv6 address:
/* Solicited-Node Multicast formula */ Prefix: ff02::1:ff00:0/104 Last 24 bits: lower 24 bits of the interface's IPv6 address /* Example */ Interface IPv6: 2001:db8::abcd:ef01 Lower 24 bits: cd:ef:01 Solicited-Node: ff02::1:ffcd:ef01 /* Why this is better than ARP broadcast */ ARP: sent to FF:FF:FF:FF:FF:FF — EVERY device on the segment must wake up and process it NDP: sent to ff02::1:ffcd:ef01 multicast — only devices whose address ends in cd:ef:01 process it (statistically, only 1–2 devices on any given segment share the same lower 24 bits) Much lower CPU overhead on large segments
NDP — NEIGHBOUR DISCOVERY PROTOCOL (REPLACES ARP + MORE)
NDP — IPv6's Supercharged ARP
OVERVIEWNeighbour Discovery Protocol (NDP, RFC 4861) replaces ARP and adds additional functions that required separate protocols in IPv4. It runs over ICMPv6 (Type 133–137) and uses multicast instead of broadcast.
NDP provides five functions:
- Address Resolution — maps IPv6 address to MAC address (replaces ARP)
- Router Discovery — hosts find routers and their prefixes automatically
- Prefix Discovery — hosts learn the network prefix for SLAAC autoconfiguration
- Redirect — routers inform hosts of better first-hop routes
- Duplicate Address Detection (DAD) — verifies an address is unique before using it
NDP Message Types
MESSAGES| ICMPv6 Type | Name | Direction | Purpose |
|---|---|---|---|
133 | Router Solicitation (RS) | Host → All-routers (ff02::2) | Host asks "any routers out there?" on startup |
134 | Router Advertisement (RA) | Router → All-nodes (ff02::1) | Router announces prefix, MTU, default gateway, flags |
135 | Neighbour Solicitation (NS) | Host → Solicited-Node multicast | Address resolution (like ARP request) + DAD |
136 | Neighbour Advertisement (NA) | Host → Requester (unicast) | Address resolution reply (like ARP reply) |
137 | Redirect | Router → Host | Better route available via different next-hop |
NDP Address Resolution — Step by Step
PROCESSScenario: Host A (2001:db8::1) wants to send a packet to Host B (2001:db8::2). It doesn't know B's MAC address.
00:00:02 → Solicited-Node = ff02::1:ff00:0002. The Ethernet multicast MAC for this is derived as 33:33:ff:00:00:02 (IPv6 multicast MAC prefix is 33:33 followed by the last 4 bytes of the multicast group).Duplicate Address Detection (DAD)
DADBefore using a new IPv6 address, a host must verify it's unique on the link via DAD. This is especially important for SLAAC-derived addresses (two devices could theoretically derive the same EUI-64 from different MAC addresses, though this is extremely rare).
/* DAD process */ 1. Host tentatively assigns the address (marks as TENTATIVE in neighbour cache) 2. Host sends NS with: - Source IP = :: (unspecified — not yet using the new address) - Destination = Solicited-Node multicast of the tentative address - Target = the tentative address itself 3. If no NA is received within RetransTimer (1 second default): → Address is unique → set to PREFERRED state → use it 4. If an NA IS received (someone already has this address): → Address conflict detected → DAD fails → Interface stays without this address → Kernel logs: "IPv6: DAD failed for address 2001:db8::1" /* On Linux you can observe DAD: */ $ ip -6 addr show dev eth0 inet6 2001:db8::1/64 scope global tentative ← DAD in progress inet6 2001:db8::1/64 scope global ← DAD passed, address active
Router Advertisement — The Key to Autoconfiguration
RA MESSAGERouter Advertisements (ICMPv6 Type 134) are sent periodically by routers to ff02::1 (all-nodes) and contain everything a host needs to configure itself:
/* Key fields in a Router Advertisement */ Cur Hop Limit: 64 # recommended Hop Limit for outgoing packets Flags: M=0 O=0 # M=1: use DHCPv6 for address; O=1: use DHCPv6 for options Router Lifetime: 1800s # how long to use this router as default gateway Reachable Time: 0 # time to assume neighbour is reachable after last confirmation Prefix Information Option: Prefix: 2001:db8::/64 Valid Lifetime: 2592000s # 30 days Preferred Lifetime: 604800s # 7 days L flag = 1 # prefix is on-link A flag = 1 # use for SLAAC autoconfiguration MTU Option: 1500 # link MTU Source Link-Layer: aa:bb:cc:dd:ee:ff # router's MAC # Receiving host uses this to: # 1. Know it's on prefix 2001:db8::/64 # 2. Auto-configure its own address (SLAAC) # 3. Set the router as default gateway (fe80::router_mac)
SLAAC AND DHCPv6 — ADDRESS AUTOCONFIGURATION
SLAAC — Stateless Address Autoconfiguration
SLAACSLAAC (RFC 4862) is IPv6's mechanism for devices to configure their own IP address without any server. A device with just a MAC address and a connected link can generate a globally routable IPv6 address in seconds — no DHCP server, no manual configuration.
SLAAC process:
EUI-64 Interface Identifier Generation
/* Derive 64-bit EUI-64 from 48-bit MAC address */ MAC: aa:bb:cc : dd:ee:ff ↓ Split: aa:bb:cc | dd:ee:ff Insert: aa:bb:cc : ff:fe : dd:ee:ff # insert ff:fe in the middle Flip: a8:bb:cc : ff:fe : dd:ee:ff # flip bit 6 (Universal/Local bit) of first byte # aa = 10101010 → bit 6 flip → 10101000 = a8 /* Example */ MAC: 00:1a:2b:3c:4d:5e EUI-64: 02:1a:2b:ff:fe:3c:4d:5e Link-Local: fe80::021a:2bff:fe3c:4d5e /* Privacy concern */ # EUI-64 embeds the MAC — tracking device across networks # RFC 8981 "Temporary Address Extensions" generates random interface IDs # Linux uses privacy extensions by default: random interface ID, rotated periodically $ sysctl net.ipv6.conf.eth0.use_tempaddr # 2 = prefer temporary addresses
DHCPv6 — Stateful and Stateless
DHCPv6DHCPv6 (RFC 8415) provides more control than SLAAC. It comes in two modes, controlled by flags in the Router Advertisement:
Stateless DHCPv6 (O flag = 1)
Host uses SLAAC for its address but queries DHCPv6 for additional configuration: DNS server addresses, domain search list, NTP servers. The DHCPv6 server doesn't track assignments.
Use when: You want SLAAC's simplicity but need to push DNS/NTP config centrally.
Stateful DHCPv6 (M flag = 1)
Host gets its entire address from DHCPv6 server (not SLAAC). Server maintains a lease database. Gives full control over address assignment — needed for environments requiring fixed address-to-host mapping.
Use when: You need to control exactly which address each device gets (servers, NGFW trusted hosts).
DUAL-STACK AND IPv4-to-IPv6 TRANSITION MECHANISMS
Dual-Stack — Running Both Simultaneously
DUAL-STACKThe most common and recommended transition approach is dual-stack: every node runs both IPv4 and IPv6 simultaneously. Each interface has both an IPv4 address and one or more IPv6 addresses. Applications connect using whichever version the network supports for the destination, with IPv6 preferred (Happy Eyeballs algorithm, RFC 8305).
# Configure dual-stack on Linux ip addr add 10.0.0.5/24 dev eth0 # IPv4 ip addr add 2001:db8::5/64 dev eth0 # IPv6 (manual) # Or let SLAAC configure IPv6 automatically # Check dual-stack status ip addr show eth0 # inet 10.0.0.5/24 brd 10.0.0.255 scope global eth0 # inet6 2001:db8::5/64 scope global # inet6 fe80::a00:27ff:fe4e:66a1/64 scope link # Connect to a dual-stack server — OS picks IPv6 first (Happy Eyeballs) curl -v https://google.com # Look for: Connected to google.com (2a00:1450:4009:820::200e) port 443 # Force IPv4 curl -4 https://google.com # Force IPv6 curl -6 https://google.com
Transition Mechanisms — When Dual-Stack Isn't Available
TUNNELLINGSometimes you need IPv6 connectivity over an IPv4-only network, or vice versa. Several tunnelling and translation mechanisms handle this:
| Mechanism | Type | How It Works | Use Case |
|---|---|---|---|
| 6in4 (SIT tunnel) | Tunnel | IPv6 packet encapsulated in IPv4 (Protocol 41). Manual configuration of endpoints. | Connecting IPv6 islands over IPv4 backbone |
| 6to4 | Tunnel | Automatic encapsulation using anycast relay. Embeds IPv4 address in IPv6 prefix 2002::/16. | Legacy — largely deprecated |
| Teredo | Tunnel | IPv6 over UDP/IPv4. Works through NAT. Used by Windows historically. | Legacy — deprecated |
| ISATAP | Tunnel | Intra-Site Automatic Tunnel — IPv6 over IPv4 within an organisation. | Enterprise internal tunnelling |
| DS-Lite | Tunnel | IPv4-in-IPv6 tunnelling + NAT. ISPs deploy this to serve IPv4 over IPv6-only infrastructure. | ISP transition — CGN replacement |
| NAT64 + DNS64 | Translation | NAT64 translates IPv6 packets to IPv4 and back. DNS64 synthesises AAAA records for IPv4-only hosts. IPv6-only clients can reach IPv4 servers. | IPv6-only mobile networks accessing IPv4 internet |
| MAP-T / MAP-E | Translation / Tunnel | Stateless mapping between IPv4 and IPv6 — no per-connection state in the provider network. | Modern ISP deployment at scale |
💡 For your NGFW: NAT64 and DNS64 are the most important transition mechanisms to support. Mobile operators (Jio included) run IPv6-only core networks with NAT64 gateways to reach IPv4 content. Your NGFW must be capable of processing both IPv6 traffic and NAT64-translated traffic correctly.
IPv4 vs IPv6 — SIDE-BY-SIDE COMPARISON
| Feature | IPv4 | IPv6 |
|---|---|---|
| Address size | 32 bits (4 bytes) | 128 bits (16 bytes) |
| Address space | ~4.3 billion | ~3.4 × 10³⁸ (340 undecillion) |
| Header size | 20–60 bytes (variable — IHL) | 40 bytes (fixed) |
| Header checksum | Yes — recomputed at every hop (TTL change) | No — removed. Upper layers have their own checksum |
| Fragmentation | By any router along the path | Source only — routers send ICMPv6 Packet Too Big |
| Broadcast | Yes — 255.255.255.255 and subnet broadcast | No broadcast — replaced by targeted multicast |
| Address resolution | ARP (L2 broadcast) | NDP (ICMPv6 multicast — more targeted) |
| Address configuration | Manual or DHCP | Manual, SLAAC (automatic), or DHCPv6 |
| NAT | Required (address exhaustion) | Not needed — every device gets global address |
| IPsec | Optional | Mandatory (specification requires support) |
| Router discovery | Manual or DHCP option 3 (default gateway) | SLAAC via RA — automatic, no DHCP needed |
| Options/extensions | In-header options (variable length, every router reads) | Extension headers (separate, most routers skip) |
| TTL/Hop Limit | TTL (8 bits) | Hop Limit (8 bits) — same mechanism, better name |
| Flow identification | No dedicated field | 20-bit Flow Label — enables hardware-accelerated per-flow routing |
| Link-local addresses | 169.254.0.0/16 (APIPA, failure indicator) | fe80::/10 — always present, used for NDP/routing |
| Loopback | 127.0.0.1 (127.0.0.0/8) | ::1/128 (single address) |
| NGFW complexity | Well-understood, mature tooling | Extension header chain requires careful inspection to avoid evasion |
IPv6 Security Considerations for NGFW
NGFW SECURITYIPv6 introduces new attack surfaces that NGFWs must handle. Many legacy firewalls only inspect IPv4 — IPv6 traffic passes uninspected, creating a bypass route. This is called an "IPv6 dark hole".
- Extension header abuse — attackers can hide payload content or confuse stateless firewalls by inserting many extension headers (Hop-by-Hop with large options, multiple Destination headers). NGFW must traverse the full extension header chain to find L4 headers.
- Routing Header type 0 (RH0) — deprecated (RFC 5095) but still sent by attackers. Allowed source routing of packets through arbitrary nodes — a DDoS amplification vector. Drop all packets with RH0.
- ICMPv6 must be allowed selectively — unlike IPv4 where you can block most ICMP, IPv6 depends on ICMPv6 for basic operation (NDP). Blocking it entirely breaks the network. Allow: Types 133–136 (NDP), 2 (Packet Too Big). Block: Type 137 (Redirect from external).
- Rogue RA attacks — any device can send a Router Advertisement claiming to be the default gateway, redirecting all traffic through itself. NGFW/switches should implement RA Guard (RFC 6105).
- Tunnelled IPv6 (6in4, Teredo) — IPv6-in-IPv4 tunnels can bypass IPv6 firewall rules. Inspect Protocol 41 packets and block unauthorised 6in4 tunnels at the perimeter.
- IPv6 fragmentation attacks — overlapping fragments, tiny fragments hiding L4 headers. NGFW must fully reassemble IPv6 fragments before inspection.
Explore IPv6 on Linux — Addresses, NDP, and SLAAC
Objective: Examine a live IPv6 stack, observe NDP in action, understand SLAAC address generation, and decode IPv6 packets with Wireshark.
ip -6 addr show. Identify: which are link-local (fe80::), which are global unicast (2001: or similar), which are temporary privacy addresses. If no global address exists, check if your router sends RAs: sudo rdisc6 eth0.ip link show eth0 MAC address, split it in half, insert ff:fe in the middle, flip bit 6 of the first byte, prepend fe80::. Compare with the actual fe80 address shown in ip addr. Do they match? If not, Linux privacy extensions may be in use.ip -6 neigh show. Ping your IPv6 default gateway (from ip -6 route show default) and watch the neighbour cache update. Compare with IPv4: ip neigh show — notice the structural similarity (IPv6 neigh = IPv4 ARP cache).icmpv6. Run sudo ip -6 neigh flush all to clear the cache, then ping6 -c 1 [your_gateway_ipv6]. You should see: NS (Neighbour Solicitation) to the Solicited-Node multicast, NA (Neighbour Advertisement) back. Expand each message and identify all ICMPv6 fields.icmpv6.type == 134 in Wireshark. You may need to wait up to 200 seconds for the next periodic RA, or trigger one with sudo ndisc6 eth0 ff02::2. Expand the RA and find: Prefix Information option (prefix, valid/preferred lifetime, A flag), MTU option, source link-layer address.from scapy.all import *; sendp(Ether(dst="33:33:00:00:00:02")/IPv6(dst="ff02::2")/ICMPv6ND_RS(), iface="eth0"). Capture the RA response that follows — you triggered SLAAC manually.IPv6 Socket Programming and Dual-Stack in C
Objective: Write a dual-stack TCP server in C that accepts both IPv4 and IPv6 connections. Understand the AF_INET6 socket API and how IPv4-mapped addresses work.
AF_INET6, SOCK_STREAM. Bind to :: (all interfaces, both IPv4 and IPv6) on port 8080. On Linux, binding to :: with IPV6_V6ONLY=0 creates a dual-stack socket that accepts both IPv4 and IPv6 connections.int sock = socket(AF_INET6, SOCK_STREAM, 0); int v6only = 0; setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)); struct sockaddr_in6 addr = {0}; addr.sin6_family = AF_INET6; addr.sin6_port = htons(8080); addr.sin6_addr = in6addr_any; /* :: — listen on all interfaces */ bind(sock, (struct sockaddr *)&addr, sizeof(addr)); listen(sock, 10);
telnet localhost 8080 (IPv4) and telnet -6 ::1 8080 (IPv6).::ffff:127.0.0.1. Detect and distinguish IPv4 vs IPv6 clients by checking the first 12 bytes of the address for the IPv4-mapped prefix (::ffff:0:0/96).getaddrinfo(NULL, "8080", &hints, &res) where hints.ai_family = AF_UNSPEC. This returns both IPv4 and IPv6 addresses — loop through and bind to all. This is how production servers handle dual-stack without caring about the specific protocol.M04 MASTERY CHECKLIST
- Can explain why IPv6 was created: IPv4 exhaustion, NAT limitations, and the design improvements
- Know that IPv6 has 128-bit addresses (2¹²⁸ ≈ 3.4 × 10³⁸) and can articulate why this is "enough"
- Can write and abbreviate IPv6 addresses correctly using both abbreviation rules (leading zero dropping, :: compression)
- Know the IPv6 header is fixed at 40 bytes and can name all 8 fields
- Know what the Flow Label is and why it helps with ECMP/RSS flow balancing
- Know that IPv6 uses Next Header (not Protocol) and can name key Next Header values: 6=TCP, 17=UDP, 58=ICMPv6, 44=Fragment
- Understand the extension header chain concept and why it is better than IPv4 options
- Know that IPv6 routers do NOT fragment — source-only fragmentation via Fragment extension header
- Can name the 6 unicast address types: GUA, Link-Local, ULA, Loopback, Unspecified, IPv4-Mapped
- Know the prefixes for each type by heart: GUA=2000::/3, link-local=fe80::/10, ULA=fd00::/8, loopback=::1
- Know the /64 boundary convention and why it is used universally for interface subnets
- Know that IPv6 has no broadcast — replaced by multicast (ff02::1 all-nodes, ff02::2 all-routers, Solicited-Node)
- Can explain the Solicited-Node multicast address construction and why it's more efficient than ARP broadcast
- Know NDP's 5 functions: address resolution, router discovery, prefix discovery, redirect, DAD
- Know the 5 NDP ICMPv6 message types and their numbers: RS(133), RA(134), NS(135), NA(136), Redirect(137)
- Understand SLAAC end-to-end: link-local generation → DAD → RS → RA → GUA generation → DAD
- Know EUI-64 derivation: split MAC, insert ff:fe, flip bit 6 of first byte
- Understand the difference between stateless DHCPv6 (O flag — options only) and stateful DHCPv6 (M flag — address + options)
- Know dual-stack: both IPv4 and IPv6 on same interface, Happy Eyeballs prefers IPv6
- Know NAT64+DNS64: IPv6-only clients reach IPv4 servers — critical for mobile (Jio) networks
- Know key IPv6 NGFW security concerns: extension header evasion, RH0 (drop it), Rogue RA, ICMPv6 filtering rules
- Know to allow ICMPv6 Types 133–136 (NDP) and 2 (Packet Too Big) — never block all ICMPv6
- Completed Lab 1: observed SLAAC, NDP, and RA in Wireshark; decoded NS/NA messages
- Completed Lab 2: wrote dual-stack C TCP server; understood IPv4-mapped addresses in AF_INET6
✅ Phase 1 Complete! You now have solid L1–L3 foundations: OSI model, Ethernet/L2, IPv4, and IPv6. Move to Phase 2 — Transport and Application Protocols, starting with M05 - TCP Internals. TCP is the most important transport protocol to understand deeply — it underpins HTTP, TLS, SSH, and every stateful NGFW connection.