Skip to content

14 — NAS Management

Overview

A NAS (Network Access Server) is the physical router or layer-3 device at the edge of the ISP network that terminates PPPoE sessions and sends authentication/accounting requests to FreeRADIUS. In PyroRadius, every customer is assigned to exactly one NAS. The NAS table stores connection credentials so the application can interact with routers directly (via RouterOS API or SNMP) and so FreeRADIUS knows which devices are authorized clients.


What a NAS Does in an ISP Network

Customer Router
      │  PPPoE dial (username/password)
 NAS Device (MikroTik / Cisco / Juniper)
      │  RADIUS Access-Request  (username, password, NAS-IP-Address)
 FreeRADIUS Server
      │  checks radcheck table:
      │    username matches? password matches? status active?
      │  RADIUS Access-Accept (Framed-IP-Address, Mikrotik-Rate-Limit, …)
 NAS assigns IP, applies rate limit
      │  RADIUS Accounting-Start (session-id, NAS-IP, Framed-IP)
 FreeRADIUS logs to radacct table

FreeRADIUS identifies the NAS by matching the NAS-IP-Address attribute in the RADIUS packet against nasname in the nas table (and against clients.conf). If the NAS IP is not in both places, FreeRADIUS will reject the request as coming from an unauthorized client.


NAS Table Structure

Table: nas

Column Type Description
id bigint PK Auto-increment primary key
nasname varchar IP address of the NAS device (must match NAS-IP-Address in RADIUS packets)
shortname varchar Human-readable label (e.g. "Tower-A-MikroTik")
type varchar Device type: mikrotik, cisco, juniper, other
ports int Number of ports (informational; used by some RADIUS policies)
community varchar SNMP community string (for SNMP-based monitoring)
description text Free-text description
status enum active / inactive
api_user varchar RouterOS API username (MikroTik only)
api_password varchar RouterOS API password (encrypted at rest)
api_port int RouterOS API port (default: 8728)
device_class varchar Optional classification (e.g. "core", "distribution", "access")
created_at timestamp
updated_at timestamp

Key Constraints

  • nasname must be globally unique — FreeRADIUS uses it as the lookup key.
  • api_password is stored encrypted using Laravel's Crypt::encrypt(). Never stored plain text.
  • status = inactive does not prevent FreeRADIUS from accepting packets (that is controlled by clients.conf); it only hides the NAS from active-use dropdowns in the UI.

NAS Types

Type Description API Support SNMP Support
mikrotik MikroTik RouterOS device Yes — RouterOS API port 8728 Yes — IF-MIB SNMP
cisco Cisco IOS/IOS-XE routers No (read-only via SNMP) Yes
juniper Juniper JunOS devices No Yes
other Any other RADIUS client No Optional

For non-MikroTik NAS types, api_user, api_password, and api_port are not used. Live traffic and session management features are MikroTik-only.


How NAS is Used in RADIUS

clients.conf (FreeRADIUS side)

For each NAS in the nas table (status=active), there must be a corresponding entry in FreeRADIUS's clients.conf:

client Tower-A-MikroTik {
    ipaddr      = 192.168.1.1      # must match nasname
    secret      = your_shared_secret
    shortname   = Tower-A
    nas_type    = other            # or mikrotik if using vendor-specific attrs
}

Without this entry, FreeRADIUS drops the RADIUS packet and authentication fails for all customers on that NAS.

nasname Matching

The NAS sends NAS-IP-Address = 192.168.1.1 in every RADIUS packet. FreeRADIUS looks up this IP in clients.conf to validate the client and find the shared secret. PyroRadius's nas.nasname field must be the same IP.

Customer-to-NAS Assignment

When a customer authenticates: 1. PPPoE connect comes in to NAS at IP 192.168.1.1. 2. NAS sends RADIUS Access-Request with NAS-IP-Address = 192.168.1.1. 3. FreeRADIUS accepts the request (client validated). 4. FreeRADIUS checks radcheck for the username. 5. FreeRADIUS checks radusergroup for group membership, fetches radgroupreply for rate limits. 6. FreeRADIUS returns Access-Accept.

PyroRadius stores customer.nas_id to know which NAS a customer belongs to, primarily for: - UI grouping (list customers by NAS) - Live traffic monitoring (which router to query) - Session kick (which router to send disconnect to) - Dealer NAS filtering (dealers only see NAS assigned to them)


Dealer NAS Pivot

Table: dealer_nas

Column Type Description
dealer_id bigint FK References users.id
nas_id bigint FK References nas.id

When a dealer creates a customer, the NAS dropdown is filtered to show only NAS entries in this pivot for their dealer ID. Admin assigns NAS to dealers via the Dealer edit page → NAS tab.

If a dealer has no NAS assigned, they cannot create customers (no valid NAS to select).


NAS Health Monitoring

PollNasPorts Command

php artisan nas:poll-ports

Scheduled to run periodically (every 5 minutes). For each active NAS: 1. Performs SNMP walk on IF-MIB::ifHCInOctets and IF-MIB::ifHCOutOctets. 2. Reads interface names from IF-MIB::ifDescr. 3. Stores readings in nas_port_readings table.

nas_port_readings Table

Column Type Description
id bigint PK
nas_id bigint FK Which NAS
port_name varchar Interface name (e.g. ether1, pppoe-out1)
in_octets bigint Total bytes in (counter, not delta)
out_octets bigint Total bytes out
recorded_at timestamp When this reading was taken

Deltas are calculated in the UI by comparing consecutive readings from this table.

PruneNasPorts Command

php artisan nas:prune-ports

Deletes nas_port_readings entries older than 7 days. Runs daily via scheduler to prevent table bloat.

NAS Status Indicator

The NAS list in the UI shows a status indicator for each NAS: - Green — last successful SNMP poll within 10 minutes - Yellow — last successful poll 10–30 minutes ago - Red — no successful poll in 30+ minutes (possible outage) - Grey — NAS is inactive (manually disabled)


NAS API Fields (MikroTik)

Field Default Notes
api_user RouterOS user with api and read permissions at minimum; write required for session kick
api_password Stored encrypted; decrypted only when building RouterOS API connection
api_port 8728 Standard RouterOS API port; API-SSL uses 8729 (not currently used)

Creating the RouterOS API User

On the MikroTik device:

/user group add name=radius-api policy=api,read,write,sensitive
/user add name=pyroradius password=YourStrongPassword group=radius-api

The write policy is required to execute /ppp/active/remove for session kicks.


SNMP Configuration

Community String

nas.community stores the SNMP v2c community string. Default on most devices is public, but this should be changed to a private string in production.

What PyroRadius Reads via SNMP

MIB OID Purpose
IF-MIB::ifDescr 1.3.6.1.2.1.2.2.1.2 Interface names
IF-MIB::ifHCInOctets 1.3.6.1.2.1.31.1.1.1.6 High-capacity bytes in (64-bit counter)
IF-MIB::ifHCOutOctets 1.3.6.1.2.1.31.1.1.1.10 High-capacity bytes out
IF-MIB::ifOperStatus 1.3.6.1.2.1.2.2.1.8 Interface up/down status

SNMP is used as a fallback for live traffic when the RouterOS API is unavailable or the NAS is non-MikroTik.

SNMP Version

Currently SNMP v2c only. v3 (with authentication and encryption) is not yet implemented.


NasController CRUD Reference

Method Route Description
index() GET /nas Paginated NAS list with status indicators
create() GET /nas/create Show create form
store() POST /nas Validate + persist NAS record
show() GET /nas/{id} NAS detail: config, port readings, customers on this NAS
edit() GET /nas/{id}/edit Edit form pre-populated
update() PUT /nas/{id} Update NAS record; re-encrypt api_password if changed
destroy() DELETE /nas/{id} Delete NAS (blocked if customers are assigned)
poll() POST /nas/{id}/poll Trigger immediate SNMP poll for this NAS
testConnection() POST /nas/{id}/test Test RouterOS API connectivity and return version string

Adding a New NAS — Step-by-Step

Step 1: Configure the MikroTik Device

# Enable RADIUS client on MikroTik
/radius add service=ppp,dhcp address=<FreeRADIUS-IP> secret=<shared_secret> timeout=3s

# Enable PPP RADIUS authentication
/ppp aaa set use-radius=yes

# Create API user for PyroRadius
/user group add name=pyroradius-api policy=api,read,write,sensitive
/user add name=pyroradius password=<api_password> group=pyroradius-api

Step 2: Add to FreeRADIUS clients.conf

On the FreeRADIUS server:

client <nas_shortname> {
    ipaddr  = <nas_ip>
    secret  = <same_shared_secret_as_mikrotik>
    nas_type = other
}

Reload FreeRADIUS: systemctl reload freeradius

Step 3: Add NAS in PyroRadius

  1. Navigate to Settings → NAS → Add NAS.
  2. Fill in:
  3. NAS Name (IP address — must match device IP exactly)
  4. Short Name
  5. Type: mikrotik
  6. SNMP Community: (your community string)
  7. API User: pyroradius
  8. API Password: (will be encrypted on save)
  9. API Port: 8728
  10. Status: Active
  11. Save.

Step 4: Assign NAS to Dealers

  1. Go to Users → select dealer → NAS tab.
  2. Check the new NAS.
  3. Save.

Dealers can now select this NAS when creating customers.

Step 5: Verify

  1. Click "Test Connection" on the NAS detail page — should return RouterOS version.
  2. Click "Poll Now" — should populate port readings.
  3. Create a test customer on this NAS and verify PPPoE authentication works.

Common NAS Issues

Symptom Likely Cause Fix
Customers can't authenticate NAS IP not in clients.conf Add to clients.conf and reload FreeRADIUS
Wrong IP in nasname NAS IP changed (DHCP) Use static IP on NAS, update nasname field
API test fails Firewall blocking port 8728 Allow 8728 from app server IP on MikroTik
SNMP poll fails Community string mismatch Verify NAS SNMP config and community field
Session kick fails API user missing write policy Add write policy to API user group on MikroTik

  • NashasMany Customer
  • NashasMany NasPortReading
  • NasbelongsToMany User (via dealer_nas)