nixos/firewall: Fixes for NAT and IPv6

This commit is contained in:
Jack O'Sullivan 2022-05-28 21:50:26 +01:00
parent 4660406120
commit 32421f7af1
2 changed files with 37 additions and 20 deletions

View File

@ -13,13 +13,13 @@ rec {
let let
v6 = isIPv6 ipp; v6 = isIPv6 ipp;
matchIP = if v6 then "[[]([0-9a-fA-F:]+)[]]" else "([0-9.]+)"; matchIP = if v6 then "[[]([0-9a-fA-F:]+)[]]" else "([0-9.]+)";
m = match "${matchIP}:([0-9-]+)" ipp; m = match "${matchIP}:(.+)" ipp;
checked = v: if m == null then throw "bad ip:ports `${ipp}'" else v; checked = v: if m == null then throw "bad ip:ports `${ipp}'" else v;
in in
{ {
inherit v6; inherit v6;
ip = checked (elemAt m 0); ip = checked (elemAt m 0);
ports = checked (replaceStrings ["-"] [":"] (elemAt m 1)); ports = checked (elemAt m 1);
}; };
naiveIPv4Gateway = ip: "${head (elemAt (split ''([0-9]+\.[0-9]+\.[0-9]+)\.[0-9]+'' ip) 1)}.1"; naiveIPv4Gateway = ip: "${head (elemAt (split ''([0-9]+\.[0-9]+\.[0-9]+)\.[0-9]+'' ip) 1)}.1";
attrsToNVList = mapAttrsToList nameValuePair; attrsToNVList = mapAttrsToList nameValuePair;

View File

@ -3,6 +3,14 @@ let
inherit (lib) optionalString concatStringsSep concatMapStringsSep optionalAttrs mkIf mkDefault mkMerge mkOverride; inherit (lib) optionalString concatStringsSep concatMapStringsSep optionalAttrs mkIf mkDefault mkMerge mkOverride;
inherit (lib.my) parseIPPort mkOpt' mkBoolOpt'; inherit (lib.my) parseIPPort mkOpt' mkBoolOpt';
forwardOpts = with lib.types; {
options = {
proto = mkOpt' (enum [ "tcp" "udp" ]) "tcp" "Protocol.";
port = mkOpt' (either port str) null "Incoming port";
dst = mkOpt' str null "Destination (ip:port).";
};
};
cfg = config.my.firewall; cfg = config.my.firewall;
iptCfg = config.networking.firewall; iptCfg = config.networking.firewall;
in in
@ -20,7 +28,8 @@ in
nat = with options.networking.nat; { nat = with options.networking.nat; {
enable = mkBoolOpt' true "Whether to enable IP forwarding and NAT."; enable = mkBoolOpt' true "Whether to enable IP forwarding and NAT.";
inherit externalInterface forwardPorts; inherit externalInterface;
forwardPorts = mkOpt' (listOf (submodule forwardOpts)) [ ] "List of port forwards.";
}; };
}; };
@ -46,6 +55,18 @@ in
} }
chain wan { chain wan {
ip protocol icmp icmp type {
destination-unreachable,
router-solicitation,
router-advertisement,
time-exceeded,
parameter-problem,
echo-request
} accept
ip protocol igmp accept
ip protocol tcp tcp flags & (fin|syn|rst|ack) == syn ct state new jump wan-tcp
ip protocol udp ct state new jump wan-udp
ip6 nexthdr icmpv6 icmpv6 type { ip6 nexthdr icmpv6 icmpv6 type {
destination-unreachable, destination-unreachable,
packet-too-big, packet-too-big,
@ -63,18 +84,8 @@ in
mld2-listener-report, mld2-listener-report,
echo-request echo-request
} accept } accept
ip protocol icmp icmp type { ip6 nexthdr tcp tcp flags & (fin|syn|rst|ack) == syn ct state new jump wan-tcp
destination-unreachable, ip6 nexthdr udp ct state new jump wan-udp
router-solicitation,
router-advertisement,
time-exceeded,
parameter-problem,
echo-request
} accept
ip protocol igmp accept
ip protocol tcp tcp flags & (fin|syn|rst|ack) == syn ct state new jump wan-tcp
ip protocol udp ct state new jump wan-udp
} }
chain input { chain input {
@ -97,7 +108,7 @@ in
} }
} }
table nat { table inet nat {
chain prerouting { chain prerouting {
type nat hook prerouting priority 0; type nat hook prerouting priority 0;
} }
@ -141,15 +152,20 @@ in
let let
makeFilter = f: makeFilter = f:
let let
ipp = parseIPPort f.destination; ipp = parseIPPort f.dst;
in in
"ip${optionalString ipp.v6 "6"} daddr ${ipp.ip} ${f.proto} dport ${toString f.sourcePort} accept"; "ip${optionalString ipp.v6 "6"} daddr ${ipp.ip} ${f.proto} dport ${toString f.port} accept";
makeForward = f: "${f.proto} dport ${toString f.sourcePort} dnat to ${f.destination}"; makeForward = f:
let
ipp = parseIPPort f.dst;
in
"${f.proto} dport ${toString f.port} dnat ip${optionalString ipp.v6 "6"} to ${f.dst}";
in in
'' ''
table inet filter { table inet filter {
chain filter-port-forwards { chain filter-port-forwards {
${concatMapStringsSep "\n " makeFilter cfg.nat.forwardPorts} ${concatMapStringsSep "\n " makeFilter cfg.nat.forwardPorts}
return
} }
chain forward { chain forward {
${optionalString ${optionalString
@ -158,9 +174,10 @@ in
} }
} }
table nat { table inet nat {
chain port-forward { chain port-forward {
${concatMapStringsSep "\n " makeForward cfg.nat.forwardPorts} ${concatMapStringsSep "\n " makeForward cfg.nat.forwardPorts}
return
} }
chain prerouting { chain prerouting {
${optionalString ${optionalString