-
Notifications
You must be signed in to change notification settings - Fork 2
radius
Pre-Alpha. This page describes behavior that may change.
Ze authenticates operator logins (SSH, web, MCP) against RADIUS servers (RFC 2865) when the system.authentication.radius block is present. It is a PAP admin-authentication backend in the AAA chain, mirroring the existing TACACS+ backend. Local bcrypt users keep working as the fallback, so an unreachable server cannot lock you out of the device.
This is the operator / admin login path. It is separate from, and does not touch, the pre-existing L2TP subscriber RADIUS path (l2tp.auth.radius), which authenticates PPP sessions and lives under the l2tp config root.
| Function | Status | Notes |
|---|---|---|
| Authentication | Production | PAP (RFC 2865 User-Password, hidden per Section 5.2 with the shared secret). |
| Authorization | Via profiles | An Access-Accept reply attribute (default Filter-Id) maps the user to local RBAC profiles. |
| Accounting | Not in MVP | Admin-session accounting is deferred; subscriber accounting stays in the L2TP path. |
system {
authentication {
radius {
server 10.0.0.1 { port 1812; key "$9$encrypted-key"; }
server 10.0.0.2 { port 1812; key "$9$encrypted-key"; }
timeout 3
retries 3
profile-attribute filter-id
default-profile read-only
}
}
authorization {
profile admin { run { default-action allow; } edit { default-action allow; } }
profile read-only { run { default-action allow; } edit { default-action deny; } }
}
}
| Leaf | Type | Default | Notes |
|---|---|---|---|
radius.server <ip> |
list, ordered | - | IPv4 only; tried in declaration order on failure. |
radius.server <ip>.port |
uint16 (1-65535) | 1812 | UDP authentication port. |
radius.server <ip>.key |
string ($9$) |
required | Shared secret, stored as ciphertext. |
radius.timeout |
uint16 (1-60) | 3 | Per-server request timeout in seconds. |
radius.retries |
uint8 (0-10) | 3 | Transmit attempts per server before failover. |
radius.source-address |
ip-address | none | Local source IP for outbound RADIUS UDP. |
radius.profile-attribute |
enum filter-id / class
|
filter-id |
Access-Accept reply attribute carrying profile names. |
radius.default-profile |
leaf-list | none | Profiles applied when the Access-Accept carries no profile-attribute. |
When RADIUS, TACACS+, and local users are all configured, the chain is tried in priority order (lower first): RADIUS, then TACACS+, then local bcrypt.
| Backend | Priority |
|---|---|
| RADIUS | 50 |
| TACACS+ | 100 |
| Local bcrypt | 200 |
The chain distinguishes two failure kinds:
- Access-Reject (explicit rejection) stops the chain immediately. Local bcrypt is NOT tried, so a wrong password against RADIUS cannot succeed via a stale local hash.
-
Timeout or all servers unreachable is treated as an infrastructure error, so the chain falls through to the next backend and ultimately to local bcrypt. A dead server, a bad
source-address, or an unreachable network never locks the operator out of SSH.
The total time one login spends talking to RADIUS is bounded, so a slow server falls through rather than hanging the login. If the RADIUS client cannot even start (for example an unbindable source-address), the backend contributes nothing and logs an error rather than failing the whole AAA bundle, so local and TACACS+ still authenticate.
Ze's authorization model is name-based, so a RADIUS-accepted user must map to one or more locally-defined system.authorization.profile entries.
- With the default
profile-attribute filter-id, each Filter-Id attribute (RFC 2865 Section 5.11) in the Access-Accept supplies one profile name; multiple Filter-Id attributes yield multiple profiles.classreads the Class attribute (Section 5.25) the same way. - When the Access-Accept carries no such attribute, the
default-profileleaf-list applies. - When neither is present the login resolves to no profile and is rejected, with a
RADIUS admin auth rejected: no profiles resolvedwarning naming the user. Ze never authorizes a user it cannot attach a profile to: an authenticated login always carries at least one profile name. The rejection stops the chain, exactly as an Access-Reject does, because the server did answer (this is not the unreachable-server case that falls through to local).
Configure the RADIUS server to return Filter-Id = admin (or your profile name) for operators, and define a matching system.authorization.profile. If your server does not send a profile attribute, set default-profile instead; otherwise no RADIUS user can log in.
A successful login is tagged in the daemon log so you can confirm which backend answered:
INFO SSH auth success subsystem=ssh username=alice remote=10.0.0.1:51408 source=radius
source=radius confirms RADIUS returned Access-Accept; source=local means RADIUS was unreachable or unconfigured and the local bcrypt user accepted the credentials.
ze doctor probes every configured RADIUS admin server with an Access-Request before the daemon starts. When none answers a verifiable response it emits doctor-radius-admin-unreachable, a warning (local fallback still works). A missing or wrong shared key counts as unreachable, because a verifiable response requires the correct shared secret. This check is distinct from the L2TP subscriber path's own doctor-radius-unreachable check.
ze doctor --json router.conf
ze explain doctor-radius-admin-unreachable
-
Shared secrets are stored as
$9$ciphertext, never plaintext. The CLI never echoes them;ze config dump --strip-privatereplaces them with/* SECRET-DATA */. - PAP only in the MVP. CHAP and EAP admin auth are follow-up work; the L2TP subscriber path already handles CHAP / MS-CHAPv2 for PPP sessions.
-
Same client as the L2TP subscriber path (
internal/component/radius), so retransmit, failover, and Response-Authenticator verification behave identically. That client isudp4, so RADIUS admin servers must be IPv4.
- TACACS+ for the sibling admin-authentication backend this mirrors.
- Web UI and System for the login surfaces and authorization profiles this backend feeds.
- RFC 2865: Remote Authentication Dial In User Service (RADIUS).
Adapted from main/docs/guide/radius.md.
Unreviewed draft. This wiki was authored in bulk and has not been reviewed. File corrections on the issue tracker.
- Overview
- YANG Model
- Editor Workflow
- Archive and Rollback
- System
- Interfaces
- VRRP
- BFD
- FIB
- OSPF
- IS-IS
- MPLS / LDP / RSVP-TE
- RSVP-TE
- SRv6
- Static Routes
- Policy Routing
- Firewall
- Traffic Control
- Class of Service
- L2TP/PPP
- PPPoE
- VPP Data Plane
- RPKI
- IPsec VPN
- TACACS+ AAA
- RADIUS AAA
- AS112 DNS
- Authorization
- Fleet
- BGP
- Starting and Stopping
- Show Commands
- Monitoring
- Flow Export
- DDoS Mitigation
- Anomaly Detection
- Health Checks
- Audit Trail
- Production Diagnostics
- Logging
- Operational Reports
- Healthcheck
- Self-Update
- Zero-Touch Provisioning
- MRT Analysis
- Upgrade and Restart
- Storage
- Policy
- Core
- Resilience
- Validation
- Capabilities
- Address Families
- Protocol
- Subsystems
- Infrastructure
- Route Server at an IXP
- Transit Edge with RPKI
- Public Looking Glass
- ExaBGP Migration Walkthrough
- FlowSpec Injection
- Chaos-Tested Peering
- AS Path Topology