conf: Containing PolyLAN specific configurationradiusd.conf/default/inner-tunnel/eap/sql: Your normal config files.
bootstrap.sh: Glues all the special cases from above together.
For development purposes:
init: Sets up the local databasetest: Sets up the local freeradius
The RADIUS server authenticates users via MAC address (MAB - MAC Authentication Bypass). On the first authentication request from an unknown device, FreeRADIUS accepts the authentication and assigns default VLAN 499.
In VLAN 499, the user is presented with the network login page provided by login-ng (dedicated app).
After a successful login, login-ng creates a bouncer (dedicated app) job that reassigns the user to the VLAN dedicated to the user switch to which the user is connected.
This works because the bouncer can access the FreeRADIUS database. On an authentication request, FreeRADIUS looks up the attributes for a specific username in the radreply table. The bouncer edits this table when a user should be relocated to a different VLAN and also triggers re-authentication of the client via Change-of-Authorization (CoA).
The bouncer sets the Cleartext-Password for a user (identified by its MAC) to its MAC address (username == password) via the radcheck table. This enables PAP authentication where the switch sends the MAC address as both username and password.
Switches use MAB (MAC Authentication Bypass) with PAP authentication.
The main reason for using MAB on a user switch is that end-user devices do not have to set up 802.1X on their devices.
- Method: User switches use MAB (MAC Authentication Bypass)
- Authentication: PAP with username = password = MAC address (lowercase, no separators)
- VLAN Assignment: FreeRADIUS returns
Tunnel-Private-Group-Id,Tunnel-Medium-Type, andTunnel-Typeattributes - CoA Port: Standard CoA port 3799 for dynamic VLAN changes
- Accounting: User switches send Start, Interim-Update, and Stop accounting packets
- Unknown device connects to switch
- Switch sends Access-Request with User-Name = MAC address (e.g.,
d45d64b09a27) - FreeRADIUS queries SQL - no entries found in
radcheckorradreply - Backwards-compatibility code triggers: accepts any password, assigns VLAN 499
- FreeRADIUS responds with Access-Accept including VLAN 499 attributes
- Switch assigns port to VLAN 499
- User authenticates via captive portal web page
bouncercreates database entries:radcheck:Cleartext-Password = "d45d64b09a27"radreply:Tunnel-Private-Group-Id = "502"(switch-specific VLAN)
bouncersends CoA to switch triggering re-authentication- Switch re-authenticates, now finds database entries, assigns to proper VLAN
- Switch sends Access-Request with User-Name = MAC address (e.g.,
d45d64b09a27) - FreeRADIUS queries SQL:
radchecktable: GetsCleartext-Password(same as MAC)radreplytable: Gets VLAN assignment (e.g.,Tunnel-Private-Group-Id = "502")
- FreeRADIUS responds with Access-Accept including VLAN attributes
- Switch assigns port to specified VLAN
- Accounting packets track session (Start, Interim-Update, Stop)
In general, the configuration files are a modified version of the default configuration files.
- Authentication Methods:
- PAP enabled for MAC authentication (username = password = MAC address)
- EAP-TTLS with MSCHAPv2 for 802.1X clients (default)
- EAP-PEAP with MSCHAPv2 also supported
- EAP-MD5 enabled for Cisco SG500x switch compatibility
- VLAN Assignment:
- Default VLAN 499 assigned during initial authentication (captive portal VLAN)
- SQL
radreplytable overrides with switch-specific VLANs (501, 502, etc.) Tunnel-Private-Group-Idcached for fast session resumption
- SQL Backend:
- MySQL database for user credentials and VLAN assignments
- Graceful degradation if database unavailable (using
-sqlprefix) - Used for: authorization, accounting, post-auth logging, session tracking
- Log to
stdoutinstead of files - Log all authentication results (both accept and reject)
- Run as
freeraduser/group
-
Authorization section:
-
Disable various modules:
filter_username,chap,mschap,digest,-ldap -
Enable SQL with
-sqlprefix (fail-safe: continues if DB unavailable) -
This backwards-compatibility validator accepts any password when no
radcheckdb table entry exists, allowing unknown devices to authenticate and are assigned to VLAN 499:if (!control:Cleartext-Password && User-Password) { update control { Cleartext-Password := "%{User-Password}" # Default VLAN for captive portal (overridden by SQL radreply): Tunnel-Private-Group-ID := "499" } }This ensures users land in VLAN 499 initially for captive portal access. The SQL
radreplytable overrides this with switch-specific VLANs after successful login.
-
-
Authentication section:
- Disable authentication modules matching disabled authorization modules
- Enable PAP for MAC authentication
-
Accounting section:
- Enable SQL accounting with
-sqlprefix - Disable
detailedandunixaccounting
- Enable SQL accounting with
-
Session section:
- Enable SQL for Simultaneous-Use checking
-
Post-Auth section:
- Enable SQL post-auth logging with
-sqlprefix
- Enable SQL post-auth logging with
- Set
default_eap_type = ttls(EAP-TTLS as primary method) - Enable EAP-MD5 for Cisco SG500x series switches
- TLS Configuration:
- Restrict to TLS 1.2 only (
tls_min_version = "1.2",tls_max_version = "1.2") - Disables TLS 1.0, 1.1, and 1.3 for maximum compatibility
- Restrict to TLS 1.2 only (
- Session Caching:
- Enable caching for fast reauthentication
- 24-hour cache lifetime
- Store
Tunnel-Private-Group-Idin cache for VLAN persistence
- TTLS Configuration:
- Set
default_eap_type = mschapv2in tunneled TLS
- Set
- PEAP Configuration:
- Also configured with MSCHAPv2 as alternative to TTLS
-
Authorization section:
- Enable
filter_username(unlike default server) - Enable
mschapmodule (required for MSCHAPv2) - Disable
chap,-ldap - Enable SQL with
-sqlprefix - Comment out
pap(not needed with MSCHAPv2)
- Enable
-
Authentication section:
- Enable
mschapfor MSCHAPv2 authentication - Disable other authentication modules
- Enable
-
Session section:
- Enable both
radutmpandsqlfor session tracking
- Enable both
- Set
dialect = "mysql" - Set
driver = "rlm_sql_${dialect}" - Disable TLS with MySQL database
- Configure database connection via environment variables:
RADIUS_DB_HOST(server)RADIUS_DB_PORT(port)RADIUS_DB_DB(database name)RADIUS_DB_USER(username)RADIUS_DB_PASSWORD(password)
- Set
read_groups = no(disable group-based authorization)
- Default VLAN 499: Custom logic to assign initial VLAN for captive portal
- SQL fail-safe mode: Using
-sqlprefix allows operation even if database is temporarily unavailable - TLS version lock: Restricted to TLS 1.2 only for compatibility
- EAP-MD5 support: Added specifically for Cisco SG500x switches
- Session caching: Stores VLAN assignment for fast reconnection
- No group support:
read_groups = nosimplifies authorization to per-user basis only
Nice explanation of the configuration:
docker-compose up --buildIn the local setup, there is a client and a user configured:
clients.conf:
client localhost {
ipaddr = 127.0.0.1
secret = testing123
}
mods-config/files/authorize:
bob Cleartext-Password := "test"
Run (within the container):
➜ docker exec -it freeradius bash
root@68babbd2d9f0:/# radtest bob test 127.0.0.1 0 testing123
Sent Access-Request Id 3 from 0.0.0.0:48770 to 127.0.0.1:1812 length 73
User-Name = "bob"
User-Password = "test"
NAS-IP-Address = 172.20.0.3
NAS-Port = 0
Message-Authenticator = 0x00
Cleartext-Password = "test"
Received Access-Accept Id 3 from 127.0.0.1:1812 to 127.0.0.1:48770 length 20