You enabled IPv6 on a Friday afternoon. The change window was clean, the ip -6 addr output looked right, smoke tests passed. By Monday, half your monitoring was green and lying to you. Your blackbox exporter was happily probing https://10.0.4.12/health over IPv4 while user traffic from mobile carriers — which are all v6-first now — fell over a cliff on a path your dashboards never touched.

That is the defining property of dual-stack failure: it doesn't break IPv4 loudly. It breaks it silently, by making IPv6 preferred (RFC 6724 address selection) and then failing on a path nobody instrumented. A broken v6 route doesn't lose to a working v4 route — it wins, and then it times out.

This guide is for sysadmins, SREs, and network/security engineers running real infrastructure. By the end you'll have working configs for Linux hosts, nginx, HAProxy, systemd-resolved, and nftables, plus a rollout order that keeps you off the 3am page. The thesis throughout: dual-stack is a policy problem disguised as a config problem. Happy Eyeballs, DNS AAAA leaks, and asymmetric firewall rules are where you actually get burned — not in ip addr add.

:::note[TL;DR]

  • IPv6 is preferred by the kernel's address selection; a broken v6 path silently beats a working v4 path. Instrument both or you're blind.
  • Write your firewall once in the inet family. Two parallel rule sets is a drift bug waiting to happen.
  • AAAA is a traffic switch. Sequence it: infra → monitoring → internal DNS → canary → full publish.
  • Never block ICMPv6 types 1–4 and 128–136. You will break PMTUD and neighbor discovery.
  • Have a five-minute AAAA rollback before you publish anything. :::

Prerequisites

  • A Linux host with a v6-capable kernel (any modern distro; check ip -6 addr returns something).
  • nftables (the default on current Debian/Ubuntu/RHEL families; iptables-nft shim is fine but write native nft).
  • nginx and/or haproxy if you're fronting traffic.
  • systemd-resolved or a resolver you control, for split-horizon testing.
  • A lab GUA (global unicast) allocation or a Hurricane Electric tunnel if your uplink has no native v6. Do not test on production first.

1. Why Dual-Stack Fails Quietly

The failure mode is baked into the standard. When a host resolves both an A and an AAAA record, the kernel's getaddrinfo ordering (RFC 6724) puts IPv6 first. Applications that don't implement Happy Eyeballs — and plenty don't — connect to the v6 address, wait for the TCP timeout, and never fall back. Even Happy Eyeballs is a client-side heuristic with roughly a 250ms head start, not a contract; servers and middleboxes still lie about reachability.

The three silent killers:

  1. Happy Eyeballs is not a guarantee. It's a race with a head start. If your v6 path black-holes packets (as opposed to sending RST), the client may still win the race to a broken socket.
  2. DNS AAAA asymmetry. Your internal resolver hands out AAAA for a host that has no v6 route back. Traffic goes into a hole.
  3. Firewall default-deny on v6 only. You carried v4 rules over but never wrote v6 equivalents — so v6 is either silently wide open or fully blocked, depending on your default policy.

Before anything else, confirm the kernel is actually doing v6 and understand what an address/route looks like:

# Confirm v6 is enabled and see the address + route reality sysctl net.ipv6.conf.all.disable_ipv6 ip -6 addr show dev eth0 ip -6 route show default 

⚠️ TRUNCATED VERSION
This is an abbreviated cross-post. Full article (all config files, architecture diagrams, images): valtersit.com

🛠️ Partner Tools for Developers

ValtersIT curates partner deals for developers and sysadmins — VPS hosting, security tools, monitoring platforms and dev productivity gear. No filler, no affiliate spam.

➜ valtersit.com/deals/