From 69a4e3a3b8c80762c4c19763882f3352870c4b10 Mon Sep 17 00:00:00 2001 From: "noussair.hamrit" Date: Wed, 15 Apr 2026 17:50:58 +0200 Subject: [PATCH] feat(freeradius): implement node pinning and dynamic IP allocation - add node pinning logic in authorize (reject if wrong node) - optimize SQL queries using control variables - assign Pool-Name dynamically for engineers - integrate sqlippool for dynamic IP allocation (engineers only) - add Session-Timeout aligned with lease_duration - fix duplicate sqlippool execution in post-auth/accounting - configure sqlippool with NAS-IP scoping for multi-node isolation Ensures correct routing, tenant isolation, and scalable IP management. --- files/mods-available/sqlippool | 4 +-- files/sites-available/default | 56 ++++++++++++++++++++++++++-------- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/files/mods-available/sqlippool b/files/mods-available/sqlippool index 4ec3d78..75d0161 100644 --- a/files/mods-available/sqlippool +++ b/files/mods-available/sqlippool @@ -30,7 +30,7 @@ sqlippool { # That way the NAS will automatically kick the user offline when the # lease expires. # - lease_duration = 86400 + lease_duration = 18000 # # Timeout between each consecutive 'allocate_clear' queries (default: 1s) @@ -76,7 +76,7 @@ sqlippool { # pool_key = "%{NAS-Port}" # pool_key = "%{Calling-Station-Id}" pool_key = "%{User-Name}" - + nas_ip_address = "%{NAS-IP-Address}" ################################################################ # # WARNING: MySQL (MyISAM) has certain limitations that means it can diff --git a/files/sites-available/default b/files/sites-available/default index 90767ec..643fa91 100644 --- a/files/sites-available/default +++ b/files/sites-available/default @@ -418,20 +418,31 @@ authorize { # # See "Authorization Queries" in mods-available/sql sql + ### Node pinning + client type (optimized) update control { - Tmp-String-0 := "%{sql:SELECT node_ip FROM node_assignments WHERE username='%{User-Name}'}" - } + Tmp-String-0 := "%{sql:SELECT node_ip FROM node_assignments WHERE username='%{User-Name}'}" + Tmp-String-1 := "%{sql:SELECT client_type FROM node_assignments WHERE username='%{User-Name}'}" + } - if (&control:Tmp-String-0 == "") { - reject - } + # No assignment → reject + if (&control:Tmp-String-0 == "") { + reject + } - if (&control:Tmp-String-0 != "%{NAS-IP-Address}") { - update reply { - Reply-Message := "Wrong node" - } - reject - } + # Wrong node → reject (string compare to avoid type mismatch) + if ("%{control:Tmp-String-0}" != "%{NAS-IP-Address}") { + update reply { + Reply-Message := "Wrong node (%{NAS-IP-Address}) expected %{control:Tmp-String-0}" + } + reject + } + + # Engineers → dynamic pool + if (&control:Tmp-String-1 == "engineer") { + update control { + Pool-Name := "engineers-%{sql:SELECT SUBSTRING_INDEX('%{User-Name}','@',-1)}" + } + } # If you are using /etc/smbpasswd, and are also doing mschap authentication, the un-comment this line, and configure the 'smbpasswd' module. # smbpasswd @@ -632,8 +643,17 @@ accounting { # Return an address to the IP Pool when we see a stop record. # Ensure that &control:Pool-Name is set to determine which pool of IPs are used. - sqlippool + # sqlippool + ### rebuild Pool-Name + update control { + Pool-Name := "engineers-%{sql:SELECT SUBSTRING_INDEX('%{User-Name}','@',-1)}" + } + + ### apply only for engineers + if (&control:Pool-Name =~ /^engineers-/) { + sqlippool + } # Log traffic to an SQL database. # See "Accounting queries" in mods-available/sql sql @@ -765,8 +785,18 @@ post-auth { # # Ensure that &control:Pool-Name is set to determine which # pool of IPs are used. - sqlippool + # sqlippool + # Engineers → dynamic IP + # + if (&control:Pool-Name =~ /^engineers-/) { + + update reply { + Session-Timeout := 3600 + } + + sqlippool +} # Create the CUI value and add the attribute to Access-Accept. # Uncomment the line below if *returning* the CUI.