diff --git a/shared/bastion.nix b/shared/bastion.nix index 0c2ec72..759886e 100644 --- a/shared/bastion.nix +++ b/shared/bastion.nix @@ -3,5 +3,7 @@ # Import dependencies imports = [ ./bastion/wireguard.nix + ./bastion/forward.nix + ./bastion/nftables.nix ]; } \ No newline at end of file diff --git a/shared/bastion/nftables.nix b/shared/bastion/nftables.nix new file mode 100644 index 0000000..29ac0b1 --- /dev/null +++ b/shared/bastion/nftables.nix @@ -0,0 +1,86 @@ +{ ... }: + +{ + networking = { + nat.enable = false; + firewall.enable = false; + nftables = { + enable = true; + checkRuleset = true; + flushRuleset = true; + tables = { + filter = { + family = "inet"; + content = '' + chain preroute { + type filter hook prerouting priority -150; policy accept; + } + chain input { + type filter hook input priority 0; policy drop; + + # Authorized already setup connection + ct state related,established accept + + # Reject sus stuff + ct state invalid counter drop + tcp flags & (fin|syn|rst|ack) != syn ct state new counter drop + + # Loopback + iif lo accept + + # ICMP + icmp type { echo-request } limit rate 4/second accept + icmpv6 type { echo-request } limit rate 4/second accept + ip protocol icmp accept + icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept + + # SSH + tcp dport 22 accept + + # Mesh + udp dport 51820 accept + + # Mgmt + udp dport 51920 accept + + # Log anything else + ip protocol tcp counter log prefix "tcp.in.dropped: " + ip protocol udp counter log prefix "udp.in.dropped: " + + } + chain forward { + type filter hook forward priority 0; policy drop; + + ct state related,established accept + ct state invalid counter drop + + iifname mgmt oifname mesh accept + } + chain output { + type filter hook output priority 0; policy accept; + } + chain postroute { + type filter hook postrouting priority 50; policy accept; + } + ''; + }; + # We'll not nat the outgoing wg packet + # Instead custom routing is done on all + # other node to sent it back correclty + # That allow for custom ACL for the mgmt + # ip addresses + nat = { + family = "inet"; + content = '' + chain prerouting { + type nat hook prerouting priority -100; policy accept; + } + chain postrouting { + type nat hook postrouting priority 100; policy accept; + } + ''; + }; + }; + }; + }; +} \ No newline at end of file diff --git a/shared/bastion/wireguard.nix b/shared/bastion/wireguard.nix index 609cc02..8a0b4a5 100644 --- a/shared/bastion/wireguard.nix +++ b/shared/bastion/wireguard.nix @@ -21,8 +21,8 @@ let name = "${peerConfig.name}"; publicKey = peerConfig.publicKey; allowedIPs = [ - "172.19..${toString (myZone + 128)}${toString peerConfig.id}/32" - "fc00:f::${toString (myZone + 128)}:${toString peerConfig.id}/128" + "172.19..${toString (myZone + 127)}${toString peerConfig.id}/32" + "fc00:f::${toString (myZone + 127)}:${toString peerConfig.id}/128" ]; persistentKeepalive = 25; }) users-wg; @@ -30,8 +30,8 @@ let interface = { "mgmt" = { ips = [ - "172.19.${toString (myZone + 128)}.254/24" - "fc00:f::${toString (myZone + 128)}:254/96" + "172.19.${toString (myZone + 127)}.254/24" + "fc00:f::${toString (myZone + 127)}:254/96" ]; privateKeyFile = config.age.secrets."wg-private-zone-${toString myZone}".path; listenPort = 51920; diff --git a/shared/commons/networking.nix b/shared/commons/networking.nix index d534e76..df2e51b 100644 --- a/shared/commons/networking.nix +++ b/shared/commons/networking.nix @@ -15,6 +15,20 @@ let # And routes, the gateway is assumed to be in subnet, otherwise GatewayOnLink is required route4 = if supportsIPv4 myNode then [{ Gateway = myNode.gIp4; }] else []; route6 = if supportsIPv6 myNode then [{ Gateway = myNode.gIp6; }] else []; + + # Return route for mgmt traffic + rtwg4 = if myNode.id == 1 then [] else + map (node: { + Gateway = "172.19.${toString node.zone}.1"; + Destination = "172.19.${toString (node.zone + 127)}.0/24"; + }) (lib.attrValues (lib.filterAttrs (name: node: node.id == 1) nodes)); + + rtwg6 = if myNode.id == 1 then [] else + map (node: { + Gateway = "fc00::${toString node.zone}:1"; + Destination = "fc00:f::${toString (node.zone + 127)}:0/96"; + }) (lib.attrValues (lib.filterAttrs (name: node: node.id == 1) nodes)); + in { networking.hostName = config.hostName;