From fd4c8ad65b504bb3726ac5ca142d58286fba211e Mon Sep 17 00:00:00 2001 From: Astro Date: Mon, 6 Sep 2021 22:08:15 +0200 Subject: [PATCH] nixos-module/container/upstream: do SNAT for forwarded ports --- nix/nixos-module/container/upstream.nix | 32 ++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/nix/nixos-module/container/upstream.nix b/nix/nixos-module/container/upstream.nix index fae8242..662a84f 100644 --- a/nix/nixos-module/container/upstream.nix +++ b/nix/nixos-module/container/upstream.nix @@ -14,7 +14,7 @@ let ) else null; - enabled = (firstUpstreamInterface != null); + enabled = firstUpstreamInterface != null; in { systemd.network.networks = { @@ -56,9 +56,9 @@ in enable = true; internalInterfaces = [ "core" ]; externalInterface = firstUpstreamInterface; - # Provide IPv6 upstream for everyone, using NAT66 when not from - # our static prefixes extraCommands = + # Provide IPv6 upstream for everyone, using NAT66 when not from + # our static prefixes builtins.concatStringsSep "\n" ( map (net: '' ip6tables -t nat -N ${net}_nat || \ @@ -76,6 +76,32 @@ in -o ${net} \ -j ${net}_nat '') (builtins.attrNames upstreamInterfaces) + ) + + # Do SNAT on connection attempts so that the actual return path + # won't matter. Forwarded ports will work from internal networks + # and on services that have Internet through another upstream routers. + builtins.concatStringsSep "\n" ( + map ({ proto, destination, sourcePort, ... }: + let + ds = builtins.split ":" destination; + ds' = + if builtins.length ds == 3 + then { + dest = lib.elemAt ds 0; + port = lib.elemAt ds 2; + } + else if builtins.length ds == 1 + then { + dest = lib.elemAt ds 0; + port = toString sourcePort; + } + else throw "Too many colons in a forwardPorts destination"; + inherit (ds') dest port; + in '' + iptables -t nat -A nixos-nat-post \ + -p ${proto} --dest ${dest} --dport ${port} \ + -j SNAT --to-source ${config.site.net.core.hosts4.${hostName}} + '') hostConf.forwardPorts ); extraStopCommands = builtins.concatStringsSep "\n" (