From 79ab172cbeb4f06606ccfc486d24a0b500c72b3c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Karel=20Ko=C4=8D=C3=AD?= <cynerd@email.cz>
Date: Wed, 18 Jan 2023 14:34:59 +0100
Subject: nixos/adm-omnia: router module

---
 nixos/machine/adm-omnia.nix | 44 ++++++++--------------------------
 nixos/modules/default.nix   |  1 +
 nixos/modules/router.nix    | 58 ++++++++++++++++++++++++++++++++++++++-------
 3 files changed, 61 insertions(+), 42 deletions(-)

(limited to 'nixos')

diff --git a/nixos/machine/adm-omnia.nix b/nixos/machine/adm-omnia.nix
index d158b45..c704b58 100644
--- a/nixos/machine/adm-omnia.nix
+++ b/nixos/machine/adm-omnia.nix
@@ -7,40 +7,16 @@
 with lib; {
   config = {
     cynerd = {
-      #openvpn.oldpersonal = true;
+      router = {
+        enable = true;
+        wan = "end2";
+        lanIP = config.cynerd.hosts.adm.omnia;
+      };
+      openvpn.oldpersonal = false;
     };
 
-    networking = {
-      # TODO we need vlan filtering to filter out guest and adm network
-      bridges = {
-        brlan = {
-          interfaces = [
-            "lan0"
-            "lan1"
-            "lan2"
-            "lan3"
-            "lan4"
-          ];
-        };
-        #brguest = {
-        #  interfaces = [
-        #    "brlan.2" #"mlan0host" "wlp1s0host"
-        #  ];
-        #};
-      };
-      interfaces.brlan = {
-        ipv4 = {
-          addresses = [
-            {
-              address = config.cynerd.hosts.adm.omnia;
-              prefixLength = 24;
-            }
-          ];
-        };
-      };
-      # TODO localhost
-      nameservers = ["1.1.1.1" "8.8.8.8"];
-      dhcpcd.allowInterfaces = ["end2"];
+    networking.bridges = {
+      brlan.interfaces = ["lan0" "lan1" "lan2" "lan3" "lan4"];
     };
 
     networking.wirelessAP = {
@@ -55,12 +31,12 @@ with lib; {
           ht_capab = ["HT40+" "LDPC" "SHORT-GI-20" "SHORT-GI-40" "TX-STBC" "RX-STBC1" "MAX-AMSDU-7935" "DSSS_CCK-40"];
           vht_capab = ["RXLDPC" "SHORT-GI-80" "TX-STBC-2BY1" "RX-ANTENNA-PATTERN" "TX-ANTENNA-PATTERN" "RX-STBC-1" "MAX-MPDU-11454" "MAX-A-MPDU-LEN-EXP7"];
           ssid = "TurrisRules5";
-          wpa = true;
+          wpa = 2;
           wpaPassphrase = "@PASS_TURRIS_RULES@";
           bss = {
             "wlp1s0host" = {
               ssid = "KocoviGuest";
-              wpa = true;
+              wpa = 2;
               wpaPassphrase = "@PASS_KOCOVI@";
             };
           };
diff --git a/nixos/modules/default.nix b/nixos/modules/default.nix
index 72221d8..bdab3b2 100644
--- a/nixos/modules/default.nix
+++ b/nixos/modules/default.nix
@@ -9,6 +9,7 @@
   cynerd-hosts = import ./hosts.nix;
   cynerd-monitoring = import ./monitoring.nix;
   cynerd-openvpn = import ./openvpn.nix;
+  cynerd-router = import ./router.nix;
   cynerd-syncthing = import ./syncthing.nix;
   cynerd-wifi-client = import ./wifi-client.nix;
 }
diff --git a/nixos/modules/router.nix b/nixos/modules/router.nix
index 00a3c03..cd7841e 100644
--- a/nixos/modules/router.nix
+++ b/nixos/modules/router.nix
@@ -15,41 +15,83 @@ in {
         description = "Enable router support";
       };
       wan = mkOption {
-        type = types.string;
+        type = types.str;
         description = "Interface for the router's WAN";
       };
       brlan = mkOption {
-        type = types.string;
+        type = types.str;
         default = "brlan";
         description = "LAN interface (commonly some bridge)";
       };
-      # TODO IP range and so on
+      lanIP = mkOption {
+        type = types.str;
+        description = "LAN IP address";
+      };
+      dynIPStart = mkOption {
+        type = types.ints.between 0 256;
+        default = 100;
+        description = "Offset for the dynamic IPv4 addresses";
+      };
+      dynIPCount = mkOption {
+        type = types.ints.between 0 256;
+        default = 100;
+        description = "Number of dynamically assigned IPv4 addresses";
+      };
+      lanPrefix = mkOption {
+        type = types.ints.between 0 32;
+        default = 24;
+        description = "LAN IP network prefix length";
+      };
     };
   };
 
-  config = mkIf cnf {
-    # TODO firewall NAT
+  config = mkIf cnf.enable {
     networking = {
+      interfaces."${cnf.brlan}" = {
+        ipv4.addresses = [
+          {
+            address = cnf.lanIP;
+            prefixLength = cnf.lanPrefix;
+          }
+        ];
+      };
+      nat = {
+        externalInterface = cnf.wan;
+        internalInterfaces = [cnf.brlan];
+      };
+      dhcpcd.allowInterfaces = [cnf.wan];
+      nameservers = ["1.1.1.1" "8.8.8.8"];
     };
 
     services.dhcpd4 = {
       enable = true;
       authoritative = true;
-      interfaces = ["brlan"];
+      interfaces = [cnf.brlan];
       extraConfig = ''
+        option domain-name-servers 1.1.1.1 8.8.8.8;
+        subnet ${ipv4.prefix2ip cnf.lanIP cnf.lanPrefix} netmask ${ipv4.prefix2netmask cnf.lanPrefix} {
+            range ${
+          ipv4.ipAdd cnf.lanIP cnf.lanPrefix cnf.dynIPStart
+        } ${
+          ipv4.ipAdd cnf.lanIP cnf.lanPrefix (cnf.dynIPStart + cnf.dynIPCount)
+        };
+            option routers ${cnf.lanIP};
+            option subnet-mask ${ipv4.prefix2netmask cnf.lanPrefix};
+            option broadcast-address ${ipv4.prefix2broadcast cnf.lanIP cnf.lanPrefix};
+        }
       '';
     };
 
     services.dhcpd6 = {
       enable = true;
       authoritative = true;
-      interfaces = ["brlan"];
+      interfaces = [cnf.brlan];
       extraConfig = ''
       '';
     };
 
     services.kresd = {
-      enable = true;
+      enable = false;
     };
   };
 }
-- 
cgit v1.2.3