feat(ap01): external RADIUS + DHCPv4 + jitterRNGd + stable bridge + default route

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
This commit is contained in:
Ryan Lahfa 2024-09-01 18:03:18 +02:00
parent 4fb39070bb
commit 0b94fb5ba7

View file

@ -5,12 +5,17 @@
... ...
}: }:
let let
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs.pseudofile) symlink dir;
inherit (pkgs) serviceFns;
svc = config.system.service; svc = config.system.service;
secrets-1 = { # secrets-1 = {
ssid = "DGNum 2G prototype (N)"; # ssid = "DGNum 2G prototype (N)";
}; # # wpa_passphrase = "diamond dogs";
# };
secrets-2 = { secrets-2 = {
ssid = "DGNum 5G prototype (AX)"; ssid = "DGNum 5G prototype (AX)";
# wpa_passphrase = "diamond dogs";
}; };
baseParams = { baseParams = {
country_code = "FR"; country_code = "FR";
@ -57,57 +62,31 @@ let
vlan_tagged_interface = "lan"; vlan_tagged_interface = "lan";
}; };
serverRadius = { externalRadius = {
radius_server_clients = pkgs.writeText "clients" '' # TODO: when we have proper IPAM, set the right value here.
0.0.0.0/0 dgnum own_ip_addr = "127.0.0.1";
''; nas_identifier = "ap01.dgnum.eu";
radius_server_auth_port = 1812;
radius_server_ipv6 = 1; # 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 = mkWifiSta =
params: interface: secrets: params: interface: secrets:
svc.hostapd.build { svc.hostapd.build {
inherit interface; inherit interface;
package = pkgs.hostapd-radius; package = pkgs.hostapd-radius;
params = params // secrets; params = params // secrets;
dependencies = [ config.services.jitter ];
}; };
in in
rec { rec {
imports = [ imports = [
"${modulesPath}/wlan.nix" "${modulesPath}/wlan.nix"
"${modulesPath}/network" "${modulesPath}/network"
"${modulesPath}/dhcp6c"
"${modulesPath}/hostapd" "${modulesPath}/hostapd"
"${modulesPath}/ssh" "${modulesPath}/ssh"
"${modulesPath}/ntp" "${modulesPath}/ntp"
@ -122,10 +101,8 @@ rec {
hostname = "ap01-prototype"; hostname = "ap01-prototype";
security.pki = { # Get moar random please
installCACerts = true; services.jitter = svc.jitter-rng.build { };
certificateFiles = [ ../../keys/certs/dgnum-test-ap-ca.crt ];
};
# SSH keys are handled by the access control module. # SSH keys are handled by the access control module.
dgn-access-control.enable = true; dgn-access-control.enable = true;
@ -136,25 +113,66 @@ rec {
passwd = "$6$jVXFFOp8HBYmgINR$lutB4kvw.W1jlXRby9ZYAgBitQ32RxQdYAGN.s2x4ris8J07vM6tzlRBQoeLELOIEMClDzbciQV0itfHQnTqd1"; 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 { services.bridge = svc.bridge.members.build {
primary = services.int; primary = services.int;
members = with config.hardware.networkInterfaces; [ members = with config.hardware.networkInterfaces; [
lan lan
wlan0 # wlan0
wlan1 wlan1
]; ];
}; };
services.dhcpv4 = services.resolvconf = oneshot rec {
let name = "resolvconf";
iface = services.int; up = ''
in . ${serviceFns}
svc.network.dhcp.client.build { interface = iface; }; ( 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 { services.defaultroute4 = svc.network.route.build {
via = "$(output ${services.dhcpv4} address)"; via = "$(output ${services.dhcpv4} router)";
target = "default"; target = "default";
dependencies = [ services.dhcpv4 ]; dependencies = [ services.dhcpv4 ];
}; };
@ -166,6 +184,8 @@ rec {
pools = { pools = {
"pool.ntp.org" = [ "iburst" ]; "pool.ntp.org" = [ "iburst" ];
}; };
dependencies = [ config.services.jitter ];
}; };
boot.tftp = { boot.tftp = {
@ -174,17 +194,16 @@ rec {
}; };
# wlan0 is the 2.4GHz interface. # wlan0 is the 2.4GHz interface.
services.hostap-1 = mkWifiSta ( # services.hostap-1 = mkWifiSta (
baseParams // clientRadius // localRadius // serverRadius // radiusKeyMgmt # baseParams // radiusKeyMgmt
) config.hardware.networkInterfaces.wlan0 secrets-1; # ) config.hardware.networkInterfaces.wlan0 secrets-1;
# wlan1 is the 5GHz interface, e.g. AX capable. # wlan1 is the 5GHz interface, e.g. AX capable.
services.hostap-2 = mkWifiSta ( services.hostap-2 = mkWifiSta (
baseParams // clientRadius // localRadius // serverRadius // radiusKeyMgmt // modernParams baseParams // clientRadius // externalRadius // radiusKeyMgmt // modernParams
) config.hardware.networkInterfaces.wlan1 secrets-2; ) config.hardware.networkInterfaces.wlan1 secrets-2;
defaultProfile.packages = with pkgs; [ defaultProfile.packages = with pkgs; [
zyxel-bootconfig zyxel-bootconfig
iw
min-collect-garbage min-collect-garbage
mtdutils mtdutils
]; ];