FreeRADIUS & Dart API Integration Saga: Resolving PPPoE Authentication Timeouts Integrasi FreeRADIUS & Dart API: Mengatasi Timeout Otentikasi PPPoE
This document provides a comprehensive historical log and architectural post-mortem of the debugging saga to transition the ISPANA Platform to a modern, stateless, dynamic client RADIUS architecture.
πΊοΈ Architectural Objective
The goal was to enable Stateless Dynamic Client Discovery and Subscriber Authentication via a REST-to-RADIUS bridge:
- Dynamic Router Registration: When an unknown MikroTik router connects, FreeRADIUS queries
/api/radius/nas?ip=...to fetch its secret and register it in-memory. - Stateless Authentication: Subscribers are authenticated dynamically via
/api/radius/authorize, querying subscriber credentials directly from the MongoDB database through the Dart API.
π The Step-by-Step Debugging Journey
π Problem 1: Stale Configuration Files (.save Conflicts)
- Symptoms: FreeRADIUS loaded duplicate client definitions and failed to start or processed requests using stale, static values.
- Root Cause: Text editors created backup files (e.g.,
/etc/freeradius/3.0/clients.d/ispana.conf.save). FreeRADIUS blindly includes all files inclients.d/regardless of extension. - Resolution: Cleaned the directory, leaving only active configuration files.
π Problem 2: API Validation & JWT Bypass (401/403 Errors)
- Symptoms: FreeRADIUS requests were rejected with
401 Unauthorizedor403 Forbiddenfrom the Dart API. - Root Causes:
- RADIUS routes were protected by global JWT middleware.
- VPN subscribers took priority over PPPoE subscribers in database lookups.
- Status validation failed because PPPoE users use
"active"while VPN users use"enabled".
- Resolution:
- Bypassed JWT validation for
/api/radius/*routes. - Reversed query priority in
vendor_remote_data_source.dart. - Updated
vendor_controller.dartto support both status types.
- Bypassed JWT validation for
π‘ Problem 3: Wildcard Client Secret Mismatch (RADIUS Timeout)
- Symptoms: When
clients.d/ispana.confwas removed to test dynamic lookups, the router loggedradius timeout. - Root Cause: FreeRADIUS matched the router to the catch-all subnet
client dynamic_network (0.0.0.0/0)which was statically set tosecret = dummy. Since the router used its true secret, signature check failed. - Resolution: Implemented the
dynamic_clientsmodule to dynamically register routers with their correct database secrets.
βοΈ Problem 4: Duplicate Virtual Server Compilation Issues
- Symptoms: Custom
authenticateblock was ignored. - Root Cause: FreeRADIUS already had a default
server dynamic-clients-serverdefined earlier. It loaded empty default block and ignored custom one. - Resolution: Deleted/commented out duplicate server definitions.
πΊοΈ Problem 5: REST Response Mapping Mismatch (Reply vs. Control)
- Symptoms: FreeRADIUS logged
Cannot add client: Required attribute "FreeRADIUS-Client-Secret" is missing. - Root Cause: The REST module (
rest_nas) parses API JSON response and puts attributes in the request's reply list. FreeRADIUS C-code strictly expects dynamic client details in the control list. - Resolution: Injected a virtual server policy (
update control) to copy attributes fromreplytocontrol.
π Problem 6: Network Listener Virtual Server Constraint
- Symptoms: FreeRADIUS logged
Cannot add client: Virtual server default is not the same as the virtual server for the network. - Root Cause: Wildcard client matched on port bound to
server default, but API returnedFreeRADIUS-Client-Virtual-Server = "dynamic_clients". - Resolution: Aligned API payload in
vendor_controller.dartto dynamically assign'FreeRADIUS-Client-Virtual-Server': 'dynamic_clients'.
π‘ Problem 7: Hardcoded C-Module Virtual Server (The Final Boss)
- Symptoms: FreeRADIUS failed to resolve dynamic clients, throwing
No such virtual server "dynamic_clients". - Root Cause:
- The
rlm_dynamic_clientsmodule has virtual server name dynamic_clients hardcoded inside its C-source code. - Because network listener on port 1812 is bound to
default, FreeRADIUS rejected registering client underdynamic_clients.
- The
- Resolution (The Alignment Hack):
- Kept network wildcard client mapping to default.
- Restored hardcoded server dynamic_clients block to run the lookup.
- Inside
server dynamic_clients'supdate controlblock, forcedFreeRADIUS-Client-Virtual-Server = "default".