From b8f25e9d80c96f7170d51eb5abcd662a66d55317 Mon Sep 17 00:00:00 2001 From: Ahmed Abdelhalim Date: Wed, 8 Jul 2026 14:28:33 +0200 Subject: Route IPv6 through WireGuard VPN via radvd and static gateway MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add radvd to gateway role to advertise Pi as high-preference IPv6 default router using the stable ULA prefix (fd1e:.../64). With FritzBox also sending RAs, devices end up with ECMP between Pi and FritzBox. To solve this, add network_ipv6_gateway (Pi's link-local) as a static route with metric 100 to all managed hosts — beats RA metric 425, ensuring all IPv6 default traffic goes through Pi. Fix IPv6 MASQUERADE in gateway-apply-rules: - Direct mode: add MASQUERADE on end0 (LAN devices use ULA source addresses not known to FritzBox, so Pi must NAT them) - FORWARD rules: restrict to RELATED,ESTABLISHED only — previously the broad ACCEPT rule passed un-NAT'd packets alongside masqueraded copies, causing duplicate SYNs, conntrack corruption, and RSTs - MASQUERADE/clear rules: match by interface not by source subnet (devices may use any source address, not just the ULA prefix) - VPN mode return traffic: explicitly restrict to wg+→end0 direction Add network_ipv6_gateway var (optional) to network role NM templates (ethernet, wifi, bridge) — injects a static IPv6 default route at metric 100 when set. Add rpi5 static route to FritzBox link-local so Pi keeps IPv6 after FritzBox RA is disabled. Force SSH to IPv4 for *.local hosts (AddressFamily inet) — prevents Ansible from hanging on mDNS returning multiple IPv6 addresses. Update gateway and pihole READMEs with two-step IPv6 setup process. Co-Authored-By: Claude.ai --- roles/network/templates/bridge.nmconnection.j2 | 5 ++++- roles/network/templates/eth0-connection.nmconnection.j2 | 3 +++ roles/network/templates/wifi-connection.nmconnection.j2 | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) (limited to 'roles/network/templates') diff --git a/roles/network/templates/bridge.nmconnection.j2 b/roles/network/templates/bridge.nmconnection.j2 index 0088a1a1..47f723d8 100644 --- a/roles/network/templates/bridge.nmconnection.j2 +++ b/roles/network/templates/bridge.nmconnection.j2 @@ -17,4 +17,7 @@ dns={{ network_ipv4_dns }} [ipv6] addr-gen-mode=default -method=disabled +method=auto +{% if network_ipv6_gateway is defined %} +routes=::/0,{{ network_ipv6_gateway }},100 +{% endif %} diff --git a/roles/network/templates/eth0-connection.nmconnection.j2 b/roles/network/templates/eth0-connection.nmconnection.j2 index b1bc87a8..d6d2ea86 100644 --- a/roles/network/templates/eth0-connection.nmconnection.j2 +++ b/roles/network/templates/eth0-connection.nmconnection.j2 @@ -32,6 +32,9 @@ addr-gen-mode=default method=disabled {% else %} method=auto +{% if network_ipv6_gateway is defined %} +routes=::/0,{{ network_ipv6_gateway }},100 +{% endif %} {% endif %} [proxy] diff --git a/roles/network/templates/wifi-connection.nmconnection.j2 b/roles/network/templates/wifi-connection.nmconnection.j2 index 3d7667c8..5b4ab185 100644 --- a/roles/network/templates/wifi-connection.nmconnection.j2 +++ b/roles/network/templates/wifi-connection.nmconnection.j2 @@ -28,5 +28,8 @@ method=auto [ipv6] addr-gen-mode=default method=auto +{% if network_ipv6_gateway is defined %} +routes=::/0,{{ network_ipv6_gateway }},100 +{% endif %} [proxy] -- cgit v1.2.3