From 0b94fb5ba74bffffffa14d9140643dc0d96cf4b0 Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Sun, 1 Sep 2024 18:03:18 +0200 Subject: [PATCH] feat(ap01): external RADIUS + DHCPv4 + jitterRNGd + stable bridge + default route Signed-off-by: Ryan Lahfa --- machines/ap01/_configuration.nix | 133 ++++++++++++++++++------------- 1 file changed, 76 insertions(+), 57 deletions(-) diff --git a/machines/ap01/_configuration.nix b/machines/ap01/_configuration.nix index 1963b67..af4cecd 100644 --- a/machines/ap01/_configuration.nix +++ b/machines/ap01/_configuration.nix @@ -5,12 +5,17 @@ ... }: let + inherit (pkgs.liminix.services) oneshot; + inherit (pkgs.pseudofile) symlink dir; + inherit (pkgs) serviceFns; svc = config.system.service; - secrets-1 = { - ssid = "DGNum 2G prototype (N)"; - }; + # secrets-1 = { + # ssid = "DGNum 2G prototype (N)"; + # # wpa_passphrase = "diamond dogs"; + # }; secrets-2 = { ssid = "DGNum 5G prototype (AX)"; + # wpa_passphrase = "diamond dogs"; }; baseParams = { country_code = "FR"; @@ -57,57 +62,31 @@ let vlan_tagged_interface = "lan"; }; - serverRadius = { - radius_server_clients = pkgs.writeText "clients" '' - 0.0.0.0/0 dgnum - ''; - radius_server_auth_port = 1812; - radius_server_ipv6 = 1; + externalRadius = { + # TODO: when we have proper IPAM, set the right value here. + own_ip_addr = "127.0.0.1"; + nas_identifier = "ap01.dgnum.eu"; + + # No DNS here, hostapd do not support this mode. + auth_server_addr = "129.199.195.129"; + auth_server_port = 1812; + auth_server_shared_secret = "read it online"; }; - localRadius = { - eap_server = 1; - eap_user_file = pkgs.writeText "user.db" '' - # anonymous login in phase 1 - * PEAP - # password based in the secure tunnel in phase 2 - "test" MSCHAPV2 "diamond dogs" [2] - ''; - - # DGNum CA certificate. - ca_cert = builtins.toFile "dgnum-test-ap-ca" ( - builtins.readFile ../../keys/certs/dgnum-test-ap-ca.crt - ); - # Server certificate for this AP. - server_cert = builtins.toFile "dgnum-ap-server" ( - builtins.readFile ../../keys/certs/dgnum-ap-server.crt - ); - private_key = builtins.toFile "dgnum-ap-server-pkey" ( - builtins.readFile ../../keys/certs/dgnum-ap-server.key.pem - ); - }; - - # externalRadius = { - # own_ip_addr = ""; - # nas_identifier = ""; - - # auth_server_addr = ""; - # auth_server_port = 1812; - # auth_server_shared_secret = "dgnum"; - # }; - mkWifiSta = params: interface: secrets: svc.hostapd.build { inherit interface; package = pkgs.hostapd-radius; params = params // secrets; + dependencies = [ config.services.jitter ]; }; in rec { imports = [ "${modulesPath}/wlan.nix" "${modulesPath}/network" + "${modulesPath}/dhcp6c" "${modulesPath}/hostapd" "${modulesPath}/ssh" "${modulesPath}/ntp" @@ -122,10 +101,8 @@ rec { hostname = "ap01-prototype"; - security.pki = { - installCACerts = true; - certificateFiles = [ ../../keys/certs/dgnum-test-ap-ca.crt ]; - }; + # Get moar random please + services.jitter = svc.jitter-rng.build { }; # SSH keys are handled by the access control module. dgn-access-control.enable = true; @@ -136,25 +113,66 @@ rec { passwd = "$6$jVXFFOp8HBYmgINR$lutB4kvw.W1jlXRby9ZYAgBitQ32RxQdYAGN.s2x4ris8J07vM6tzlRBQoeLELOIEMClDzbciQV0itfHQnTqd1"; }; - services.int = svc.bridge.primary.build { ifname = "int"; }; + services.int = svc.bridge.primary.build { + ifname = "int"; + macAddressFromInterface = config.hardware.networkInterfaces.lan; + }; services.bridge = svc.bridge.members.build { primary = services.int; members = with config.hardware.networkInterfaces; [ lan - wlan0 + # wlan0 wlan1 ]; }; - services.dhcpv4 = - let - iface = services.int; - in - svc.network.dhcp.client.build { interface = iface; }; + services.resolvconf = oneshot rec { + name = "resolvconf"; + up = '' + . ${serviceFns} + ( in_outputs ${name} + for i in $(output ${services.dhcpv4} dns); do + echo "nameserver $i" >> resolv.conf + done + ) + ''; + + dependencies = [ + config.services.dhcpv4 + ]; + }; + + filesystem = dir { + etc = dir { + "resolv.conf" = symlink "${config.services.resolvconf}/.outputs/resolv.conf"; + }; + }; + + services.dhcpv4 = svc.network.dhcp.client.build { + interface = config.services.int; + dependencies = [ + config.services.hostname + config.services.bridge + ]; + }; + + services.dhcpv6 = svc.dhcp6c.client.build { + interface = config.services.int; + dependencies = [ + config.services.hostname + config.services.bridge + ]; + }; + + services.ipv6 = svc.dhcp6c.address.build { + interface = config.services.int; + client = config.services.dhcpv6; + dependencies = [ config.services.hostname ]; + }; services.defaultroute4 = svc.network.route.build { - via = "$(output ${services.dhcpv4} address)"; + via = "$(output ${services.dhcpv4} router)"; target = "default"; dependencies = [ services.dhcpv4 ]; }; @@ -166,6 +184,8 @@ rec { pools = { "pool.ntp.org" = [ "iburst" ]; }; + + dependencies = [ config.services.jitter ]; }; boot.tftp = { @@ -174,17 +194,16 @@ rec { }; # wlan0 is the 2.4GHz interface. - services.hostap-1 = mkWifiSta ( - baseParams // clientRadius // localRadius // serverRadius // radiusKeyMgmt - ) config.hardware.networkInterfaces.wlan0 secrets-1; + # services.hostap-1 = mkWifiSta ( + # baseParams // radiusKeyMgmt + # ) config.hardware.networkInterfaces.wlan0 secrets-1; # wlan1 is the 5GHz interface, e.g. AX capable. services.hostap-2 = mkWifiSta ( - baseParams // clientRadius // localRadius // serverRadius // radiusKeyMgmt // modernParams + baseParams // clientRadius // externalRadius // radiusKeyMgmt // modernParams ) config.hardware.networkInterfaces.wlan1 secrets-2; defaultProfile.packages = with pkgs; [ zyxel-bootconfig - iw min-collect-garbage mtdutils ];