How RADIUS Works, Message by Message
A RADIUS authentication is a short UDP conversation between a network access server (NAS), such as a VPN gateway or Wi-Fi controller, and a RADIUS server: an Access-Request, possibly an Access-Challenge and a second request, and finally an Access-Accept or Access-Reject, followed by accounting. Each packet is a fixed header plus attributes defined in RFC 2865. This page decodes each packet with fake values, ties every attribute to its section, and lists what both sides must check, with particular attention to the Blast-RADIUS lessons. For what RADIUS is and its status, see the RADIUS standard page.
Addresses below are from the documentation ranges in RFC 5737. The shared secret is never sent; it only feeds the hashes.
The sequence at a glance
| # | From → to | Packet (Code) | Spec |
|---|---|---|---|
| 1 | NAS → server (UDP 1812) | Access-Request (1) with username and password | §4.1 |
| 2 | Server → NAS | Access-Challenge (11) with State and a prompt |
§4.4 |
| 3 | NAS → server | Access-Request (1) with the code and the same State |
§5.24 |
| 4 | Server → NAS | Access-Accept (2) or Access-Reject (3) | §4.2, §4.3 |
| 5 | NAS → server (UDP 1813) | Accounting-Request (4), Start | RFC 2866 §4.1 |
| 6 | Server → NAS | Accounting-Response (5) | RFC 2866 §4.2 |
With push-based MFA, steps 2 and 3 disappear: the server holds the first request while it waits for the user to approve on their phone.
The packet header
Code (1 byte) | Identifier (1) | Length (2) | Authenticator (16) | Attributes ...
0x01 0x2a 0x00b4 9f 3c 1e ... (random)
| Field | Meaning | Spec |
|---|---|---|
| Code | 1 Access-Request, 2 Access-Accept, 3 Access-Reject, 11 Access-Challenge; 4 and 5 for accounting. | §3, RFC 2866 §3 |
| Identifier | Matches replies to requests; also used to detect retransmissions. | §3 |
| Length | 20 to 4096 octets. | §3 |
| Request Authenticator | In Access-Request, 16 unpredictable random octets. Also the input to the User-Password keystream. |
§3 |
| Response Authenticator | In replies, MD5(Code + ID + Length + RequestAuth + Attributes + Secret). The only built-in integrity check, and the one Blast-RADIUS forged. |
§3 |
| Attributes | Type (1 byte), Length (1 byte), Value. | §5 |
Message 1: Access-Request
Code 1 (Access-Request) Identifier 42 Authenticator 0x9f3c1e7a...(16 random octets)
80 Message-Authenticator = 0x5b0e...(HMAC-MD5 over the packet)
1 User-Name = "ada@example.com"
2 User-Password = 0x6c1a...(16 octets, hidden with the shared secret)
4 NAS-IP-Address = 192.0.2.10
32 NAS-Identifier = "vpn-gw-01"
5 NAS-Port = 0
61 NAS-Port-Type = Virtual (5)
6 Service-Type = Framed (2)
31 Calling-Station-Id = "203.0.113.45"
30 Called-Station-Id = "198.51.100.1"
| Attribute (type) | Meaning | Spec |
|---|---|---|
| Message-Authenticator (80) | HMAC-MD5 over the whole packet, keyed with the shared secret. Mandatory with EAP; send it always. | RFC 3579 §3.2 |
| User-Name (1) | The identity being authenticated. | §5.1 |
| User-Password (2) | Password padded to 16-octet blocks and XORed with MD5(secret + RequestAuthenticator), chained per block. Confidential only as long as the secret is. |
§5.2 |
| CHAP-Password (3), alternative | CHAP response instead of a password; a request must not carry both. | §5.3, §4.1 |
| NAS-IP-Address (4) / NAS-Identifier (32) | Which NAS is asking; at least one is required. | §5.4, §5.32 |
| NAS-Port (5), NAS-Port-Type (61) | Port and its type; 5 is Virtual, used for VPN sessions. | §5.5, §5.41 |
| Service-Type (6) | Requested service, for example Framed (2) for a network session or Administrative (6) for device management. | §5.6 |
| Calling-Station-Id (31) | The caller's side. Defined for the phone number a call came from; in practice NAS vendors put the client IP for VPN or the MAC address for Wi-Fi here. Useful for policy and logs. | §5.31 |
| Called-Station-Id (30) | The called side, originally the dialed number; vendors commonly use the VPN address or the access point MAC and SSID. | §5.30 |
Messages 2 and 3: Access-Challenge for a one-time code
Code 11 (Access-Challenge) Identifier 42 Authenticator 0x...(Response Authenticator)
80 Message-Authenticator = 0x...
18 Reply-Message = "Enter the 6-digit code from your authenticator app"
24 State = 0x7f2c9a41e3b0...(opaque to the NAS)
Code 1 (Access-Request) Identifier 43 Authenticator 0x...(new random)
80 Message-Authenticator = 0x...
1 User-Name = "ada@example.com"
2 User-Password = 0x...(the one-time code, hidden as above)
24 State = 0x7f2c9a41e3b0...(copied unchanged)
4 NAS-IP-Address = 192.0.2.10
State must be returned unmodified and the NAS must not interpret it (§5.24); Reply-Message is text to display (§5.18). EAP (for 802.1X) uses exactly this challenge loop, with each round's EAP packet in EAP-Message (79) (RFC 3579 §3.1).
Message 4: Access-Accept
Code 2 (Access-Accept) Identifier 43 Authenticator 0x...(Response Authenticator)
80 Message-Authenticator = 0x... -- first attribute, per Blast-RADIUS guidance
25 Class = "sess-8c41-example"
27 Session-Timeout = 28800
11 Filter-Id = "vpn-finance"
26 Vendor-Specific = (vendor 9, a group or VLAN assignment)
| Attribute (type) | Meaning | Spec |
|---|---|---|
| Class (25) | Opaque value the NAS must echo in accounting, tying the session to this authorization. | §5.25 |
| Session-Timeout (27) | Maximum session length in seconds. | §5.27 |
| Filter-Id (11) | Name of a filter or policy the NAS applies. | §5.11 |
| Vendor-Specific (26) | Vendor ID plus vendor-defined sub-attributes, commonly used for roles and VLANs. | §5.26 |
An Access-Reject (3) may carry a Reply-Message and nothing that grants access.
Messages 5 and 6: accounting
Code 4 (Accounting-Request) Identifier 7
40 Acct-Status-Type = Start (1)
44 Acct-Session-Id = "00000A1F"
1 User-Name = "ada@example.com"
25 Class = "sess-8c41-example"
4 NAS-IP-Address = 192.0.2.10
The server answers Accounting-Response (5). Stop records carry duration and byte counts. Accounting is how you prove which user held which address at what time (RFC 2866 §5.1, §5.5).
The checks each side must run
NAS (the RADIUS client)
- Identifier and source. Accept a reply only if its Identifier matches an outstanding request and it came from the configured server address (§3).
- Response Authenticator verifies with the shared secret; otherwise silently discard (§3).
- Require
Message-Authenticatoron every reply, verify it, and expect it as the first attribute of Access-Accept and Access-Reject. This is the Blast-RADIUS mitigation; RFC 3579 §3.2 already requires it for EAP. - Return
Stateunchanged and never act on its contents (§5.24).
RADIUS server
- Known client and secret. Silently discard packets from clients without a configured shared secret (§2), and use a distinct secret per NAS, at least 16 octets and never empty (§3, Administrative Note).
- Well-formed request. Require
NAS-IP-AddressorNAS-Identifier, and exactly one ofUser-Password,CHAP-PasswordorState, never both password types (§4.1). - Require
Message-Authenticatoron requests and drop requests without it; for EAP, RFC 3579 §3.2 says such requests SHOULD be silently discarded. - Protect the transport. Across any network you do not fully control, run RADIUS inside TLS: RadSec (RFC 6614, port 2083) or RADIUS/1.1 (RFC 9765), which removes the MD5 constructions altogether.
Common implementation mistakes, with the CVEs and techniques behind them
| Mistake | What goes wrong | Real examples |
|---|---|---|
PAP or CHAP without Message-Authenticator |
An attacker in the path forges Access-Accept from Access-Reject with an MD5 collision; MFA behind RADIUS is bypassed | CVE-2024-3596 (Blast-RADIUS) |
Message-Authenticator sent but not required |
Downgrade: the attacker strips it and the old attack works | Same CVE; configure "require" on both sides |
| RADIUS server management plane exposed | The network access control system itself is taken over | CVE-2026-76460 (Cisco ISE, exploited) |
| Push MFA through RADIUS without number matching | Users approve attacker-initiated logins | MFA fatigue and push bombing |
| RADIUS-fronted VPN with password-only users | Internet-facing guessing against the directory behind it | Password spraying, credential stuffing |
| One shared secret for every NAS, never rotated | One compromised device decrypts every password and forges every reply | Rotate and segment secrets, then move to TLS |
Try it locally
There is no SWI browser tool for RADIUS, which runs over UDP. FreeRADIUS's radclient sends test packets against a lab server: radclient -x 192.0.2.20 auth example-shared-secret reads attributes from standard input and prints the reply, and its -b flag enforces the Blast-RADIUS checks, requiring Message-Authenticator as the first attribute of every reply. If your server's replies fail with -b, fix the server before relying on RADIUS for MFA.
Related
RADIUS standard page, how LDAP works, message by message, how Kerberos works, message by message, how WebAuthn works, message by message. Glossary: RADIUS, MFA, phishing-resistant MFA.
Frequently asked questions
- What is in a RADIUS Access-Request?
- A RADIUS Access-Request (Code 1) carries a one-byte Identifier, a length, a 16-byte random Request Authenticator, and attributes. RFC 2865 section 4.1 requires a NAS-IP-Address or NAS-Identifier and one of User-Password, CHAP-Password or State, and recommends User-Name and NAS-Port or NAS-Port-Type. Typical requests also carry Calling-Station-Id, Called-Station-Id, Service-Type and, since Blast-RADIUS, a Message-Authenticator.
- How does a NAS know an Access-Accept is genuine?
- It checks that the Identifier matches an outstanding request and recomputes the Response Authenticator, MD5 over the code, identifier, length, the original Request Authenticator, the attributes and the shared secret, as RFC 2865 section 3 defines. Because MD5 collisions made that forgeable (Blast-RADIUS, CVE-2024-3596), the NAS should also require a valid Message-Authenticator, an HMAC-MD5 over the whole packet defined in RFC 3579 section 3.2, on every response.
- How does MFA work over RADIUS?
- Either the RADIUS server triggers a push or call after checking the password and holds the Access-Request until the user approves, or it returns Access-Challenge with a State attribute and a Reply-Message prompting for a code. The NAS shows the prompt, then sends a new Access-Request containing the code as User-Password and the State value unchanged, as RFC 2865 section 5.24 requires.
Related on Start with Identity
- GuideHow OpenID Connect Works, Message by Message
OpenID Connect on the wire: discovery, the authentication request, the callback, the token request with PKCE, the token response and a decoded ID token, with ev
- GuideHow SAML 2.0 Works, Message by Message
A field-by-field walkthrough of the SAML 2.0 Web Browser SSO profile: the AuthnRequest, the Response and Assertion, the bindings that carry them, the eight chec
- GuideHow SCIM 2.0 Works, Message by Message
SCIM 2.0 on the wire: discovery, filtered lookup, user creation, PATCH for attribute changes and deactivation, group membership changes and DELETE, with annotat
- ArticleReusable Identity Verification: How Verify-Once-Reuse-Many Works
Reusable identity verification lets people verify once and reuse the result across services. How it works, the cost and fraud economics, the role of government
- CVEruby-saml 2024 auth bypass (ahacker1), still in the blast radius
The original 2024 ruby-saml authentication bypass (CVSS 10.0). It is outside the last twelve months, but every 2025 ruby-saml CVE is an incomplete-fix descendan