From 1cbb9df950175e698e1edc87953e8f4bfb22b88a Mon Sep 17 00:00:00 2001 From: Ahmed Abdelhalim Date: Thu, 9 Jul 2026 22:57:11 +0200 Subject: Fix IPv6 first-request failure caused by ICMPv6 Redirects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause: Pi, the ISP router (FritzBox), and LAN clients share the same L2 segment. When Pi forwards a client's IPv6 packet to an external GUA destination, the Linux kernel detects that the ISP router is a "better" next-hop on the same link and sends an ICMPv6 Redirect (type 137) to the client. The client obeys the redirect and sends its first SYN to the ISP router directly — Pi never forwards the original packet. The ISP router applies per-device content filtering to the unmasqueraded client GUA and issues a RST. This produced the symptom of the first IPv6 request failing with "Connection reset by peer" every ~30-60 seconds (matching the FritzBox RA interval, after which clients re-resolve their default gateway). Diagnosis method: tcpdump with MAC addresses (-e flag) on Pi's end0 caught the ICMPv6 Redirect being sent immediately after the first SYN arrived. Inserting a DROP rule for icmpv6-type redirect at position 1 in ip6tables OUTPUT confirmed the fix — 0 failures across extended testing. Fix: - Drop ICMPv6 Redirect (type 137) in ip6tables OUTPUT as the first rule, before the ACCEPT rule, in both direct and VPN modes - Flush ip6tables OUTPUT chain on clear_rules() instead of per-rule -D deletion, which was fragile and left stale rules accumulating across mode switches (previously caused duplicate/conflicting OUTPUT rules) - Flush ip6tables nat POSTROUTING table instead of per-rule -D deletion for the same reason Also documents the ICMPv6 Redirect issue and IPv6 masquerade rationale in roles/gateway/README.md for future reference. Co-Authored-By: Claude Sonnet 4.6 --- site.yml | 1 + 1 file changed, 1 insertion(+) (limited to 'site.yml') diff --git a/site.yml b/site.yml index 7f9a4745..94e2e831 100644 --- a/site.yml +++ b/site.yml @@ -17,6 +17,7 @@ async: 60 poll: 5 failed_when: false + changed_when: false - name: "Host Configure" ansible.builtin.import_playbook: "configure.yml" -- cgit v1.2.3