Fix VPN traffic routing issue with iptables NAT rules

The MASQUERADE rules had policy matching (-m policy --pol none --dir out)
which was preventing both WireGuard AND IPsec traffic from being NAT'd
properly. This policy match was incorrect and broke internet routing for
all VPN clients.

The confusion arose because:
- IPsec FORWARD rules check for --pol ipsec (encrypted traffic)
- But POSTROUTING happens AFTER decryption, so packets no longer have policy
- The --pol none match was blocking these decrypted packets from NAT

Changes:
- Removed policy matching from both IPsec and WireGuard NAT rules
- Both VPN types now use simple source-based NAT rules
- Applied to both IPv4 and IPv6 rule templates

This fixes the issue where VPN clients (both WireGuard and IPsec) could
connect but not route traffic to the internet.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Dan Guido 2025-08-17 16:12:56 -04:00
parent 454faa96b1
commit d5f88ddc49
2 changed files with 16 additions and 2 deletions

View file

@ -36,7 +36,14 @@ COMMIT
-A PREROUTING --in-interface {{ ansible_default_ipv4['interface'] }} -p udp --dport {{ wireguard_port_avoid }} -j REDIRECT --to-port {{ wireguard_port_actual }}
{% endif %}
# Allow traffic from the VPN network to the outside world, and replies
-A POSTROUTING -s {{ subnets | join(',') }} -m policy --pol none --dir out {{ '-j SNAT --to ' + snat_aipv4 if snat_aipv4 else '-j MASQUERADE' }}
{% if ipsec_enabled %}
# For IPsec traffic - NAT the decrypted packets from the VPN subnet
-A POSTROUTING -s {{ strongswan_network }} {{ '-j SNAT --to ' + snat_aipv4 if snat_aipv4 else '-j MASQUERADE' }}
{% endif %}
{% if wireguard_enabled %}
# For WireGuard traffic - NAT packets from the VPN subnet
-A POSTROUTING -s {{ wireguard_network_ipv4 }} {{ '-j SNAT --to ' + snat_aipv4 if snat_aipv4 else '-j MASQUERADE' }}
{% endif %}
COMMIT

View file

@ -35,7 +35,14 @@ COMMIT
-A PREROUTING --in-interface {{ ansible_default_ipv6['interface'] }} -p udp --dport {{ wireguard_port_avoid }} -j REDIRECT --to-port {{ wireguard_port_actual }}
{% endif %}
# Allow traffic from the VPN network to the outside world, and replies
-A POSTROUTING -s {{ subnets | join(',') }} -m policy --pol none --dir out {{ '-j SNAT --to ' + ipv6_egress_ip | ansible.utils.ipaddr('address') if alternative_ingress_ip else '-j MASQUERADE' }}
{% if ipsec_enabled %}
# For IPsec traffic - NAT the decrypted packets from the VPN subnet
-A POSTROUTING -s {{ strongswan_network_ipv6 }} {{ '-j SNAT --to ' + ipv6_egress_ip | ansible.utils.ipaddr('address') if alternative_ingress_ip else '-j MASQUERADE' }}
{% endif %}
{% if wireguard_enabled %}
# For WireGuard traffic - NAT packets from the VPN subnet
-A POSTROUTING -s {{ wireguard_network_ipv6 }} {{ '-j SNAT --to ' + ipv6_egress_ip | ansible.utils.ipaddr('address') if alternative_ingress_ip else '-j MASQUERADE' }}
{% endif %}
COMMIT