nixos/firewall: Fixes for NAT and IPv6
This commit is contained in:
		
							
								
								
									
										4
									
								
								lib.nix
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								lib.nix
									
									
									
									
									
								
							@@ -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;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user