fix(awg): auto-enable Docker IPv6 so dual-stack instances actually work - #103
Open
leonidorlov-hash wants to merge 3 commits into
Open
fix(awg): auto-enable Docker IPv6 so dual-stack instances actually work#103leonidorlov-hash wants to merge 3 commits into
leonidorlov-hash wants to merge 3 commits into
Conversation
…l IPv6
Dual-stack instances silently ended up IPv4-only: the panel writes v6
addresses into configs and NAT66 rules, but the Docker daemon defaults
to IPv4, so containers had no v6 route out (ping6 -> Network unreachable,
clients got no IPv6 despite fd42:: addresses in their configs).
prepare_host now checks for a global IPv6 address on the host, and if
/etc/docker/daemon.json lacks ipv6 support: backs it up (daemon.json.bak.awp),
merges in {"ipv6": true, "fixed-cidr-v6": "fd00:42::/64"} (python3 merge,
fallback to a fresh file when python3 is missing), and restarts docker.
Runs once; skipped on IPv4-only hosts and when already enabled.
Even with an IPv6-enabled daemon, containers are created with net.ipv6.conf.*.disable_ipv6=1, and the flag is fixed at netns creation. awg-quick then fails on 'ip -6 address add' (RTNETLINK: Permission denied) and rolls back by deleting awg0 entirely, killing IPv4 too. Detect host IPv6 before docker run and pass the sysctls at creation.
Without ip6tables Docker creates no MASQUERADE rule for the fixed-cidr-v6 ULA subnet, so container v6 traffic leaves with an unroutable address. Keys are now enforced unconditionally (docker restarted only on change) so hosts that already have ipv6:true still pick up the missing ip6tables/experimental keys.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The panel already writes dual-stack configs (
fd42:8:1::/64server address,fd42:8:1::N/128peer addresses, NAT66 rules), but on a stock Docker install the daemon runs IPv4-only. Containers then have no IPv6 route out:Result: clients receive
fd42:...addresses in their configs, but IPv6 traffic silently doesn't work — the tunnel is de facto IPv4-only. Reproduced on Debian 13 and Ubuntu 20.04 with default Docker settings.Fix — three layers, all required
1. Enable IPv6 + NAT66 in the Docker daemon (
prepare_host(), runs before every AWG instance install)When the host has a global IPv6 address, the panel now enforces four keys in
/etc/docker/daemon.json(merged, never overwriting other settings; backed up todaemon.json.bak.awp):"ipv6": true+"fixed-cidr-v6": "fd00:42::/64"— containers get v6 addressing and a default route"experimental": true+"ip6tables": true— without these Docker programs no NAT66 MASQUERADE rule for the ULA subnet, so v6 packets leave the host with an unroutablefd00:42::source and blackholeDocker is restarted only when the file actually changed. Keys are enforced unconditionally, so hosts that already have
"ipv6": truebut lackip6tablesstill get fixed on the next install. IPv4-only hosts are untouched.2. Enable IPv6 inside the container netns at creation time (
docker run)Even with an IPv6-enabled daemon, containers are created with
net.ipv6.conf.all.disable_ipv6 = 1, and that flag is fixed at network-namespace creation — it cannot be changed afterwards:Worse, awg-quick's rollback deletes the whole interface, so a failed IPv6 address add takes the working IPv4 tunnel down with it — the instance looks installed but passes no traffic at all.
So host IPv6 is detected before
docker runand--sysctl net.ipv6.conf.all.disable_ipv6=0+net.ipv6.conf.default.disable_ipv6=0are passed at container creation. On IPv4-only hosts the sysctls are omitted, behaviour unchanged.Testing
Verified on live servers (Debian 13), layer by layer:
ip -6 address addfailed with Permission denied and awg-quick deleted awg0 — tunnel fully dead.ip6tables: interface up, v6 address and default route present, but ping6 100% loss — no NAT66 MASQUERADE on the host.disable_ipv6 = 0,fd00:42::addressing works, host hasMASQUERADE ... fd00:42::/64, ping6 succeeds, clients get working IPv6 through the tunnel (test-ipv6.com 10/10).