Harden WireGuard VPN configuration

- Add IPv6 ip6tables rules to prevent IPv6 traffic leaks (forwarding was
  enabled but only IPv4 masquerade existed)
- Tighten FORWARD chain: only allow wg0→internet and established return,
  instead of blanket ACCEPT from wg0
- Scope NAT masquerade to VPN subnet only
- Block VPN clients from server-local services (SSH/80/443) via INPUT rules
- Set UFW DEFAULT_FORWARD_POLICY=ACCEPT (required for VPN routing; base
  hardening sets default deny which blocks forwarded packets)
- Add SaveConfig = false to prevent runtime state overwriting config
- Add reload ufw handler

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
n0mad1k
2026-03-09 15:59:02 -04:00
parent 3a909867af
commit 20bcecbcec
3 changed files with 48 additions and 9 deletions
+30 -3
View File
@@ -24,13 +24,39 @@
SERVER_PRIVKEY=$(cat /etc/wireguard/server_private.key)
IFACE={{ primary_interface.stdout | trim }}
cat > /etc/wireguard/wg0.conf << EOF
cat > /etc/wireguard/wg0.conf << 'WGEOF'
[Interface]
WGEOF
# Write dynamic values separately to avoid heredoc variable issues
cat >> /etc/wireguard/wg0.conf << EOF
Address = {{ wg_subnet | regex_replace('/\\d+$', '') | regex_replace('\\.[0-9]+$', '.1/24') }}
ListenPort = {{ wg_port }}
PrivateKey = ${SERVER_PRIVKEY}
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o ${IFACE} -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o ${IFACE} -j MASQUERADE
SaveConfig = false
# IPv4: forward VPN traffic to internet, masquerade source
PostUp = iptables -A FORWARD -i wg0 -o ${IFACE} -j ACCEPT
PostUp = iptables -A FORWARD -i ${IFACE} -o wg0 -m state --state RELATED,ESTABLISHED -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o ${IFACE} -s {{ wg_subnet }} -j MASQUERADE
# IPv6: same rules to prevent leaks
PostUp = ip6tables -A FORWARD -i wg0 -o ${IFACE} -j ACCEPT
PostUp = ip6tables -A FORWARD -i ${IFACE} -o wg0 -m state --state RELATED,ESTABLISHED -j ACCEPT
PostUp = ip6tables -t nat -A POSTROUTING -o ${IFACE} -j MASQUERADE
# Block VPN clients from accessing server-local services (except DNS if local)
PostUp = iptables -I INPUT -i wg0 -p tcp --dport 22 -j DROP
PostUp = iptables -I INPUT -i wg0 -p tcp --dport 80 -j DROP
PostUp = iptables -I INPUT -i wg0 -p tcp --dport 443 -j DROP
PostDown = iptables -D FORWARD -i wg0 -o ${IFACE} -j ACCEPT
PostDown = iptables -D FORWARD -i ${IFACE} -o wg0 -m state --state RELATED,ESTABLISHED -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o ${IFACE} -s {{ wg_subnet }} -j MASQUERADE
PostDown = ip6tables -D FORWARD -i wg0 -o ${IFACE} -j ACCEPT
PostDown = ip6tables -D FORWARD -i ${IFACE} -o wg0 -m state --state RELATED,ESTABLISHED -j ACCEPT
PostDown = ip6tables -t nat -D POSTROUTING -o ${IFACE} -j MASQUERADE
PostDown = iptables -D INPUT -i wg0 -p tcp --dport 22 -j DROP
PostDown = iptables -D INPUT -i wg0 -p tcp --dport 80 -j DROP
PostDown = iptables -D INPUT -i wg0 -p tcp --dport 443 -j DROP
EOF
@@ -38,6 +64,7 @@
CLIENT_PUBKEY=$(cat /etc/wireguard/clients/client${i}_public.key)
CLIENT_PSK=$(cat /etc/wireguard/clients/client${i}_psk.key)
cat >> /etc/wireguard/wg0.conf << EOF
[Peer]
# Client ${i}
PublicKey = ${CLIENT_PUBKEY}