shinobu/router: Fix VPN bypass
This now actually works and I have a better understanding of nftables. Some of my learnings are documented as comments in the rules.
This commit is contained in:
parent
caac620ea6
commit
9c42cb0903
|
@ -29,7 +29,7 @@
|
||||||
let
|
let
|
||||||
domain = "home.sbruder.de";
|
domain = "home.sbruder.de";
|
||||||
|
|
||||||
noVpnFwMark = 10000;
|
vpnBypassFwMark = 10000;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
sops.secrets.wg-upstream-private-key = {
|
sops.secrets.wg-upstream-private-key = {
|
||||||
|
@ -61,6 +61,7 @@ in
|
||||||
define VUEKO_PORT = 51820
|
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 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 PLASTIC_ROUTER_V4 = 192.168.0.1
|
||||||
|
define VPN_BYPASS_MARK = ${toString vpnBypassFwMark}
|
||||||
|
|
||||||
table inet filter {
|
table inet filter {
|
||||||
chain forward {
|
chain forward {
|
||||||
|
@ -75,14 +76,16 @@ in
|
||||||
iifname $NAT_LAN_IFACES oifname $NAT_WAN_IFACES counter accept
|
iifname $NAT_LAN_IFACES oifname $NAT_WAN_IFACES counter accept
|
||||||
iifname $NAT_WAN_IFACES oifname $NAT_LAN_IFACES ct state established,related 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
|
# plastic router
|
||||||
iifname $NAT_LAN_IFACES oifname $PHYSICAL_WAN ip daddr $PLASTIC_ROUTER_V4 counter accept
|
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
|
# all destinations configured via policy based routing
|
||||||
iifname $PHYSICAL_WAN oifname $NAT_LAN_IFACES ip saddr $VUEKO_V4 udp sport $VUEKO_PORT ct state established,related counter accept
|
oifname $PHYSICAL_WAN mark $VPN_BYPASS_MARK 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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
chain output {
|
||||||
type route hook output priority mangle
|
type route hook output priority mangle
|
||||||
|
jump common
|
||||||
|
}
|
||||||
|
|
||||||
# Add fwmark noVpnMark to packets to vueko, so it will get routed correctly
|
# This does not need to be of type route
|
||||||
ip daddr $VUEKO_V4 udp dport $VUEKO_PORT mark set ${toString noVpnFwMark} counter
|
chain prerouting {
|
||||||
ip6 daddr $VUEKO_V6 udp dport $VUEKO_PORT mark set ${toString noVpnFwMark} counter
|
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 {
|
table inet restrict-wan {
|
||||||
# Priorities must be higher than filter (0),
|
# Priorities must be higher than filter (0),
|
||||||
# which the NixOS firewall uses.
|
# which the NixOS firewall uses.
|
||||||
|
|
||||||
chain input {
|
chain input {
|
||||||
type filter hook input priority -50; policy accept
|
type filter hook input priority -50; policy accept
|
||||||
|
|
||||||
# accept responses
|
# accept responses
|
||||||
iifname $PHYSICAL_WAN ct state established,related counter accept
|
iifname $PHYSICAL_WAN ct state established,related counter accept
|
||||||
|
|
||||||
# accept icmpv6
|
# accept icmpv6
|
||||||
iifname $PHYSICAL_WAN icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept
|
iifname $PHYSICAL_WAN icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept
|
||||||
|
|
||||||
# drop everything else
|
# drop everything else
|
||||||
iifname $PHYSICAL_WAN counter drop
|
iifname $PHYSICAL_WAN counter drop
|
||||||
}
|
}
|
||||||
|
|
||||||
chain output {
|
# This handles all packets (local and forwarded)
|
||||||
type filter hook output priority -50; policy accept
|
chain postrouting {
|
||||||
|
type filter hook postrouting priority 0; policy accept
|
||||||
|
|
||||||
# accept connections to plastic router
|
# 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
|
# accept icmpv6
|
||||||
oifname $PHYSICAL_WAN icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept
|
oifname $PHYSICAL_WAN icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept
|
||||||
|
|
||||||
# accept connections to selected endpoints
|
# accept connections to selected endpoints
|
||||||
oifname $PHYSICAL_WAN ip daddr $WG_UPSTREAM_ENDPOINT counter accept
|
# VPN (wg-upstream)
|
||||||
oifname $PHYSICAL_WAN ip daddr $VUEKO_V4 counter accept
|
oifname $PHYSICAL_WAN ip daddr $WG_UPSTREAM_ENDPOINT counter accept # only this is used
|
||||||
oifname $PHYSICAL_WAN ip6 daddr $VUEKO_V6 counter accept
|
# destinations configured in VPN bypass
|
||||||
|
oifname $PHYSICAL_WAN mark $VPN_BYPASS_MARK counter accept
|
||||||
|
|
||||||
# drop all other packets
|
# drop all other packets
|
||||||
oifname $PHYSICAL_WAN counter drop
|
oifname $PHYSICAL_WAN counter drop
|
||||||
}
|
}
|
||||||
|
@ -260,12 +286,11 @@ in
|
||||||
Priority = 9;
|
Priority = 9;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
# vueko (v4) for wg-home
|
# VPN bypass
|
||||||
{
|
{
|
||||||
routingPolicyRuleConfig = {
|
routingPolicyRuleConfig = {
|
||||||
To = "168.119.176.53";
|
Family = "both"; # welcome in the year 2023, where ipv4 is the default
|
||||||
|
FirewallMark = vpnBypassFwMark;
|
||||||
FirewallMark = noVpnFwMark;
|
|
||||||
Priority = 9;
|
Priority = 9;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue