netns: factor the netns setup/teardown into distinct services, rather than trying to piggyback network-local-commands
idk what network-local-commands is about, nor network-pre.target. network-pre.target doesn't seem to actually be wanted by anything (?)
This commit is contained in:
parent
8523b406ad
commit
09a615ee62
|
@ -26,9 +26,10 @@ let
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
mkNetNsConfig = name: opts: with opts; {
|
mkNetNsConfig = name: opts: with opts; {
|
||||||
networking.localCommands = let
|
systemd.services."netns-${name}" = let
|
||||||
iptables = "${pkgs.iptables}/bin/iptables";
|
ip = lib.getExe' pkgs.iproute2 "ip";
|
||||||
in-ns = "ip netns exec ${name}";
|
iptables = lib.getExe pkgs.iptables;
|
||||||
|
in-ns = "${ip} netns exec ${name}";
|
||||||
bridgePort = port: proto: ''
|
bridgePort = port: proto: ''
|
||||||
${in-ns} ${iptables} -A PREROUTING -t nat -p ${proto} --dport ${port} -m iprange --dst-range ${netnsPubIpv4} \
|
${in-ns} ${iptables} -A PREROUTING -t nat -p ${proto} --dport ${port} -m iprange --dst-range ${netnsPubIpv4} \
|
||||||
-j DNAT --to-destination ${hostVethIpv4}
|
-j DNAT --to-destination ${hostVethIpv4}
|
||||||
|
@ -41,55 +42,59 @@ let
|
||||||
config.sane.ports.ports
|
config.sane.ports.ports
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
in ''
|
in {
|
||||||
ip netns add ${name} || (test -e /run/netns/${name} && echo "${name} already exists")
|
description = "create a network namespace which will selectively bridge traffic with the init namespace";
|
||||||
# DOCS:
|
# specifically, we need to set these up before wireguard-wg-*,
|
||||||
# - some of this approach is described here: <https://josephmuia.ca/2018-05-16-net-namespaces-veth-nat/>
|
wantedBy = [ "network-pre.target" ];
|
||||||
# - iptables primer: <https://danielmiessler.com/study/iptables/>
|
before = [ "network-pre.target" ];
|
||||||
# create veth pair
|
serviceConfig.Type = "oneshot";
|
||||||
ip link add ${name}-veth-a type veth peer name ${name}-veth-b || echo "${name}-veth-{a,b} aleady exists"
|
serviceConfig.RemainAfterExit = true;
|
||||||
ip addr add ${hostVethIpv4}/24 dev ${name}-veth-a || echo "${name}-veth-a aleady has IP address"
|
script = ''
|
||||||
ip link set ${name}-veth-a up
|
${ip} netns add ${name} || (test -e /run/netns/${name} && echo "${name} already exists")
|
||||||
|
# DOCS:
|
||||||
|
# - some of this approach is described here: <https://josephmuia.ca/2018-05-16-net-namespaces-veth-nat/>
|
||||||
|
# - iptables primer: <https://danielmiessler.com/study/iptables/>
|
||||||
|
# create veth pair
|
||||||
|
${ip} link add ${name}-veth-a type veth peer name ${name}-veth-b || echo "${name}-veth-{a,b} aleady exists"
|
||||||
|
${ip} addr add ${hostVethIpv4}/24 dev ${name}-veth-a || echo "${name}-veth-a aleady has IP address"
|
||||||
|
${ip} link set ${name}-veth-a up
|
||||||
|
|
||||||
# move veth-b into the namespace
|
# move veth-b into the namespace
|
||||||
ip link set ${name}-veth-b netns ${name} || echo "${name}-veth-b was already moved into its netns"
|
${ip} link set ${name}-veth-b netns ${name} || echo "${name}-veth-b was already moved into its netns"
|
||||||
${in-ns} ip addr add ${netnsVethIpv4}/24 dev ${name}-veth-b || echo "${name}-veth-b aleady has IP address"
|
${in-ns} ${ip} addr add ${netnsVethIpv4}/24 dev ${name}-veth-b || echo "${name}-veth-b aleady has IP address"
|
||||||
${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.
|
||||||
ip rule add from ${hostVethIpv4} lookup ${name} pref 50 || echo "${name} already has ip rules (pref 50)"
|
${ip} rule add from ${hostVethIpv4} lookup ${name} pref 50 || echo "${name} already has ip rules (pref 50)"
|
||||||
|
|
||||||
# for traffic originating at the host veth to the WAN, use the veth as our gateway
|
# for traffic originating at the host veth to the WAN, use the veth as our gateway
|
||||||
# not sure if the metric 1002 matters.
|
# not sure if the metric 1002 matters.
|
||||||
ip route add default via ${netnsVethIpv4} dev ${name}-veth-a proto kernel src ${hostVethIpv4} metric 1002 table ${name} || \
|
${ip} route add default via ${netnsVethIpv4} dev ${name}-veth-a proto kernel src ${hostVethIpv4} metric 1002 table ${name} || \
|
||||||
echo "${name} already has default route"
|
echo "${name} already has default route"
|
||||||
# give the default route lower priority
|
# 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 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)"
|
${ip} rule del from all lookup local pref 0 || echo "${name}: already removed ip rule of default lookup (pref 0)"
|
||||||
|
|
||||||
# in order to access DNS in this netns, we need to route it to the VPN's nameservers
|
# in order to access DNS in this netns, we need to route it to the VPN's nameservers
|
||||||
# - alternatively, we could fix DNS servers like 1.1.1.1.
|
# - alternatively, we could fix DNS servers like 1.1.1.1.
|
||||||
${in-ns} ${iptables} -A OUTPUT -t nat -p udp --dport 53 -m iprange --dst-range 127.0.0.53 \
|
${in-ns} ${iptables} -A OUTPUT -t nat -p udp --dport 53 -m iprange --dst-range 127.0.0.53 \
|
||||||
-j DNAT --to-destination ${dns}:53
|
-j DNAT --to-destination ${dns}:53
|
||||||
'' + (lib.concatStringsSep "\n" bridgeStatements);
|
'' + (lib.concatStringsSep "\n" bridgeStatements);
|
||||||
|
preStop = ''
|
||||||
|
${in-ns} ${ip} link del ${name}-veth-b || echo "couldn't delete ${name}-veth-b"
|
||||||
|
${ip} link del ${name}-veth-a || echo "couldn't delete ${name}-veth-a"
|
||||||
|
${ip} netns delete ${name} || echo "couldn't delete ${name}"
|
||||||
|
# restore rules/routes
|
||||||
|
${ip} rule del from ${hostVethIpv4} lookup ${name} pref 50 || echo "couldn't delete init -> ${name} rule"
|
||||||
|
${ip} route del default via ${netnsVethIpv4} dev ${name}-veth-a proto kernel src ${hostVethIpv4} metric 1002 table ${name} || echo "couldn't delete init > ${name} route"
|
||||||
|
# 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
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
# postShutdown = ''
|
# for some reason network-pre doesn't actually get run before network.target by default??
|
||||||
# ${in-ns} ip link del ${name}-veth-b || echo "couldn't delete ${name}-veth-b"
|
|
||||||
# ip link del ${name}-veth-a || echo "couldn't delete ${name}-veth-a"
|
|
||||||
# ip netns delete ${name} || echo "couldn't delete ${name}"
|
|
||||||
# # restore rules/routes
|
|
||||||
# ip rule del from ${veth-host-ip} lookup ${name} pref 50 || echo "couldn't delete init -> ${name} rule"
|
|
||||||
# ip route del default via ${veth-local-ip} dev ${name}-veth-a proto kernel src ${veth-host-ip} metric 1002 table ${name} || echo "couldn't delete init > #{name} route"
|
|
||||||
# ip rule add from all lookup local pref 0
|
|
||||||
# ip rule del from all lookup local pref 100
|
|
||||||
# '';
|
|
||||||
|
|
||||||
# specifically, we need to set these up before wireguard-wg-*,
|
|
||||||
# whose unit files are BEFORE "network.target", and therefore
|
|
||||||
# ordered ambiguously w.r.t. network-local-commands (a dep of "network.target").
|
|
||||||
systemd.services.network-local-commands.wantedBy = [ "network-pre.target" ];
|
|
||||||
systemd.services.network-local-commands.before = [ "network-pre.target" ];
|
|
||||||
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" ];
|
||||||
|
|
||||||
|
@ -116,7 +121,7 @@ in
|
||||||
networking.localCommands = f.networking.localCommands;
|
networking.localCommands = f.networking.localCommands;
|
||||||
networking.iproute2.rttablesExtraConfig = f.networking.iproute2.rttablesExtraConfig;
|
networking.iproute2.rttablesExtraConfig = f.networking.iproute2.rttablesExtraConfig;
|
||||||
networking.iproute2.enable = f.networking.iproute2.enable;
|
networking.iproute2.enable = f.networking.iproute2.enable;
|
||||||
systemd.services.network-local-commands = f.systemd.services.network-local-commands;
|
systemd.services = f.systemd.services;
|
||||||
systemd.targets.network-pre = f.systemd.targets.network-pre;
|
systemd.targets.network-pre = f.systemd.targets.network-pre;
|
||||||
};
|
};
|
||||||
in take (sane-lib.mkTypedMerge take configs);
|
in take (sane-lib.mkTypedMerge take configs);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user