diff --git a/machines/shinobu/services/router.nix b/machines/shinobu/services/router.nix index ca3bcbe..8da8d35 100644 --- a/machines/shinobu/services/router.nix +++ b/machines/shinobu/services/router.nix @@ -29,7 +29,7 @@ let domain = "home.sbruder.de"; - noVpnFwMark = 10000; + vpnBypassFwMark = 10000; in { sops.secrets.wg-upstream-private-key = { @@ -61,6 +61,7 @@ in define VUEKO_PORT = 51820 define WG_UPSTREAM_ENDPOINT = ${lib.elemAt (lib.splitString ":" (lib.elemAt config.systemd.network.netdevs.wg-upstream.wireguardPeers 0).wireguardPeerConfig.Endpoint) 0} define PLASTIC_ROUTER_V4 = 192.168.0.1 + define VPN_BYPASS_MARK = ${toString vpnBypassFwMark} table inet filter { chain forward { @@ -75,14 +76,16 @@ in iifname $NAT_LAN_IFACES oifname $NAT_WAN_IFACES counter accept iifname $NAT_WAN_IFACES oifname $NAT_LAN_IFACES ct state established,related counter accept + # accept responses on physical wan + iifname $PHYSICAL_WAN oifname $NAT_LAN_IFACES ct state established,related counter accept + + # allow selected destinations via physical wan + # plastic router iifname $NAT_LAN_IFACES oifname $PHYSICAL_WAN ip daddr $PLASTIC_ROUTER_V4 counter accept - iifname $PHYSICAL_WAN oifname $NAT_LAN_IFACES ip saddr $PLASTIC_ROUTER_V4 ct state established,related counter accept - iifname $NAT_LAN_IFACES oifname $PHYSICAL_WAN ip daddr $VUEKO_V4 udp dport $VUEKO_PORT counter accept - iifname $PHYSICAL_WAN oifname $NAT_LAN_IFACES ip saddr $VUEKO_V4 udp sport $VUEKO_PORT ct state established,related counter accept - iifname $NAT_LAN_IFACES oifname $PHYSICAL_WAN ip6 daddr $VUEKO_V6 udp dport $VUEKO_PORT counter accept - iifname $PHYSICAL_WAN oifname $NAT_LAN_IFACES ip6 saddr $VUEKO_V6 udp sport $VUEKO_PORT ct state established,related counter accept + # all destinations configured via policy based routing + oifname $PHYSICAL_WAN mark $VPN_BYPASS_MARK counter accept } } @@ -97,13 +100,28 @@ in } } - table inet mangle { + # Bypass VPN by setting mark. + # This acts in two places that are handled separatly by nftables: + # Packets from the local host (output hook) and forwared packets (prerouting hook). + # To simplify the handling, + # there is a single chain that handles both, + # which is jumped to from the specific chains. + table inet vpn-bypass { + # This must be of type route, otherwise no route lookup will be performed chain output { type route hook output priority mangle + jump common + } - # Add fwmark noVpnMark to packets to vueko, so it will get routed correctly - ip daddr $VUEKO_V4 udp dport $VUEKO_PORT mark set ${toString noVpnFwMark} counter - ip6 daddr $VUEKO_V6 udp dport $VUEKO_PORT mark set ${toString noVpnFwMark} counter + # This does not need to be of type route + chain prerouting { + type filter hook prerouting priority mangle + jump common + } + + chain common { + ip daddr $VUEKO_V4 udp dport $VUEKO_PORT mark set $VPN_BYPASS_MARK counter + ip6 daddr $VUEKO_V6 udp dport $VUEKO_PORT mark set $VPN_BYPASS_MARK counter } } @@ -112,27 +130,35 @@ in table inet restrict-wan { # Priorities must be higher than filter (0), # which the NixOS firewall uses. - chain input { type filter hook input priority -50; policy accept + # accept responses iifname $PHYSICAL_WAN ct state established,related counter accept + # accept icmpv6 iifname $PHYSICAL_WAN icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept + # drop everything else iifname $PHYSICAL_WAN counter drop } - chain output { - type filter hook output priority -50; policy accept + # This handles all packets (local and forwarded) + chain postrouting { + type filter hook postrouting priority 0; policy accept + # accept connections to plastic router - oifname $PHYSICAL_WAN ip daddr $PLASTIC_ROUTER_V4 accept + oifname $PHYSICAL_WAN ip daddr $PLASTIC_ROUTER_V4 counter accept + # accept icmpv6 oifname $PHYSICAL_WAN icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept + # accept connections to selected endpoints - oifname $PHYSICAL_WAN ip daddr $WG_UPSTREAM_ENDPOINT counter accept - oifname $PHYSICAL_WAN ip daddr $VUEKO_V4 counter accept - oifname $PHYSICAL_WAN ip6 daddr $VUEKO_V6 counter accept + # VPN (wg-upstream) + oifname $PHYSICAL_WAN ip daddr $WG_UPSTREAM_ENDPOINT counter accept # only this is used + # destinations configured in VPN bypass + oifname $PHYSICAL_WAN mark $VPN_BYPASS_MARK counter accept + # drop all other packets oifname $PHYSICAL_WAN counter drop } @@ -260,12 +286,11 @@ in Priority = 9; }; } - # vueko (v4) for wg-home + # VPN bypass { routingPolicyRuleConfig = { - To = "168.119.176.53"; - - FirewallMark = noVpnFwMark; + Family = "both"; # welcome in the year 2023, where ipv4 is the default + FirewallMark = vpnBypassFwMark; Priority = 9; }; }