netns: simplify the host -> netns response tunneling

i don't actually need any route table that's higher priority than 'local'
This commit is contained in:
2024-11-11 11:02:42 +00:00
parent 4604117184
commit ec5e8a3269
3 changed files with 20 additions and 17 deletions

View File

@@ -141,5 +141,10 @@ in
# }; # };
}; };
systemd.services.hickory-dns-doof.after = [
# service will fail to bind the veth, otherwise
"netns-doof-veth.service"
];
sane.services.dyn-dns.restartOnChange = lib.map (c: "${c.service}.service") (builtins.attrValues config.sane.services.hickory-dns.instances); sane.services.dyn-dns.restartOnChange = lib.map (c: "${c.service}.service") (builtins.attrValues config.sane.services.hickory-dns.instances);
} }

View File

@@ -61,8 +61,7 @@ let
in { in {
systemd.targets."netns-${name}" = { systemd.targets."netns-${name}" = {
description = "create a network namespace which will selectively bridge traffic with the init namespace"; description = "create a network namespace which will selectively bridge traffic with the init namespace";
wantedBy = [ "default.target" "network-pre.target" ]; wantedBy = [ "default.target" ];
before = [ "network-pre.target" ]; #< TODO: this is probably not needed anymore
}; };
systemd.services."netns-${name}" = { systemd.services."netns-${name}" = {
description = "create an empty network namespace for ${name}"; description = "create an empty network namespace for ${name}";
@@ -101,26 +100,17 @@ let
${in-ns} ${ip} link set ${name}-veth-b up ${in-ns} ${ip} link set ${name}-veth-b up
# make it so traffic originating from the host side of the veth # make it so traffic originating from the host side of the veth
# is sent over the veth no matter its destination. # is sent over the veth no matter its destination (well, unless it's to another interface that exists on the host).
${ip} rule add from ${veth.initns.ipv4} lookup ${name} pref 50 || echo "${name} already has ip rules (pref 50)" ${ip} rule add from ${veth.initns.ipv4} lookup ${name} pref 50 || echo "${name} already has ip rules (pref 50)"
${ip} route add default via ${veth.netns.ipv4} dev ${name}-veth-a proto kernel src ${veth.initns.ipv4} table ${name} || \
# for traffic originating at the host veth to the WAN, use the veth as our gateway
# not sure if the metric 1002 matters.
${ip} route add default via ${veth.netns.ipv4} dev ${name}-veth-a proto kernel src ${veth.initns.ipv4} metric 1002 table ${name} || \
echo "${name} already has default route" echo "${name} already has default route"
# give the default route lower priority
${ip} rule add from all lookup local pref 100 || echo "${name}: already has ip rules (pref 100)"
${ip} rule del from all lookup local pref 0 || echo "${name}: already removed ip rule of default lookup (pref 0)"
''; '';
serviceConfig.ExecStopPost = [ serviceConfig.ExecStopPost = [
"-${in-ns} ${ip} link del ${name}-veth-b" "-${in-ns} ${ip} link del ${name}-veth-b"
"-${ip} link del ${name}-veth-a" "-${ip} link del ${name}-veth-a"
# restore rules/routes # restore rules/routes
"-${ip} rule del from ${veth.initns.ipv4} lookup ${name} pref 50" "-${ip} rule del from ${veth.initns.ipv4} lookup ${name} pref 50"
"-${ip} route del default via ${veth.netns.ipv4} dev ${name}-veth-a proto kernel src ${veth.initns.ipv4} metric 1002 table ${name}" "-${ip} route del default via ${veth.netns.ipv4} dev ${name}-veth-a proto kernel src ${veth.initns.ipv4} table ${name}"
# FIXME: if there are other net namespaces active, changing the prefs here may break those!
"-${ip} rule add from all lookup local pref 0"
"-${ip} rule del from all lookup local pref 100"
]; ];
}; };
systemd.services."netns-${name}-forwards" = { systemd.services."netns-${name}-forwards" = {
@@ -221,9 +211,15 @@ let
systemd.targets.network-pre.wantedBy = [ "network.target" ]; systemd.targets.network-pre.wantedBy = [ "network.target" ];
systemd.targets.network-pre.before = [ "network.target" ]; systemd.targets.network-pre.before = [ "network.target" ];
# create a new routing table that we can use to proxy traffic out of the root namespace # i want IP routes such that any packets sent from the initns veth -- regardless of destination -- are tunneled through the VPN.
# through the wireguard namespaces, and to the WAN via VPN. # that's source policy routing. normal `ip route` only allows routing based on the destination address.
# i think the numbers here aren't particularly important. #
# to achieve source policy routing:
# - create a new routing table.
# - `ip rule` which assigns every packet with matching source into that routing table.
# - within the routing table, use ordinary destination policy routing.
#
# each routing table has a numeric ID associated with it. i think the number doesn't impact anything, it just needs to be unique.
networking.iproute2.rttablesExtraConfig = '' networking.iproute2.rttablesExtraConfig = ''
${builtins.toString routeTable} ${name} ${builtins.toString routeTable} ${name}
''; '';

View File

@@ -190,6 +190,8 @@ let
# XXX: all my wireguard DNS endpoints are static at the moment, so refresh logic isn't needed. # XXX: all my wireguard DNS endpoints are static at the moment, so refresh logic isn't needed.
# re-enable this should that ever change. # re-enable this should that ever change.
# N.B.: systemd will still bring up the device and even the peer if it fails to resolve the endpoint.
# but it seems that it'll try to re-resolve the endpoint again later (unclear how to configure this better).
# systemd.services."${name}-refresh" = { # systemd.services."${name}-refresh" = {
# # periodically re-apply peers, to ensure DNS mappings stay fresh # # periodically re-apply peers, to ensure DNS mappings stay fresh
# # borrowed from <repo:nixos/nixpkgs:nixos/modules/services/networking/wireguard.nix> # # borrowed from <repo:nixos/nixpkgs:nixos/modules/services/networking/wireguard.nix>