FreeRADIUS InkBridge

Processing Packets

This page walks through the packet processing output of FreeRADIUS version 4, line by line. It follows on from Startup Text: once the server has printed Ready to process requests, this is what you see when packets arrive.

The output on this page authenticates a user bob with the pap module. Two requests are shown:

  • request (0) with a wrong password (rejected) and request

  • request (1) with the correct password (accepted).

Request numbers

Every line for a packet starts with a request number in parentheses, for example, (0). The number lets you match up all the messages for one packet when the output contains messages from multiple packets which are interleaved due to threading.

Receiving a packet

The first message for a new packet comes from the network listener proto_radius_udp, and does not yet have a request number:

proto_radius_udp - Received Access-Request ID 3 length 61 radius_udp server * port 1812

All further processing for the request happens inside a virtual server, which shows the virtuakl server name on the next line, in this case default {. The following messages shows the packet type, the RADIUS ID, the source and destination address and port, and the network interface.

(0) default {
(0)   Received Access-Request ID 104 from 127.0.0.1:58504 to 127.0.0.1:1812 via lo0

After the Received message, the server prints the attributes which it received in the packet. For RADIUS, there are also some attributes added by the server which describe the packet. A Net attribute which contains the IP addresses and ports (source and destination) socket details, and a Packet attribute which contains the RADIUS header information. Finally, the Packet-Type attribute gives the packet type.

(0)      Message-Authenticator = 0xce9fbd43b2b13998783af1081aa112e3
(0)      User-Name = bob
(0)      User-Password = <<< secret >>>
(0)      Net = {
(0)        Src = {
(0)          IP = 127.0.0.1
(0)          Port = 52356
(0)        }
(0)        Dst = {
(0)          IP = 127.0.0.1
(0)          Port = 1812
(0)        }
(0)        Timestamp = 2026-06-12T22:08:14Z
(0)        Interface = lo
(0)      }
(0)      Packet = {
(0)        Id = 3
(0)        Authenticator = 0x03e0b76e3a5ee133d76ab8bd8e767a70
(0)      }
(0)      Packet-Type = Access-Request
In v4, secret values such as User-Password are redacted to <<< secret >>> by default, controlled by the suppress_secrets setting in the log section of the main radiusd.conf configuration file. This allows you to share debug output without risk. Set suppress_secrets = no if you need to see the real value of the secret while debugging.
If an attribute is not printed here, then it was not in the packet. No amount of changing the server configuration will add an attribute that the NAS did not send. If you need an attribute to be present, you must configure the NAS to send it.

The recv Access-Request section

In v4, we now call the first processing section recv Access-Request. In version 3 this section was called authorize. Its job is the same: look up the user in a database, determine what type of authentication to use, and set up the Auth-Type control attribute that tells the server which authenticate section to run next.

(0)   Running 'recv Access-Request' from file ./raddb/sites-enabled/default
(0)   recv Access-Request {

The Running line names the section which is being run, and the file where the section was loaded from. If you suspect that the server isn’t using the configuration you’re editing, you can use this information to double-check where the server is loading its policies from.

Each module in the section runs in order. Messages which come from a module are prefixed with the module’s name and ` - `. After the module returns, the server prints the module name and its return code in parentheses.

(0)     files - Looking for key "bob"
(0)     files - Found match "bob" on line 169 of ./raddb/mods-config/files/authorize
(0)     files (ok)
(0)     pap - Setting control.Auth-Type = pap
(0)     pap (updated)
(0)   } # recv Access-Request ((updated))

See the module rcode page for the meaning and behavior of the various return codes such as ok or updated.

In this output, the files module finds the user bob in the users file and sets control.Password.Cleartext from the entry there, returning ok. The pap module then sees a known-good password is available, sets control.Auth-Type = pap, and returns updated.

The section closes with } # recv Access-Request updated, so the final return code of the section is updated.

When you are diagnosing a problem, read this section carefully to answer:

  • Was the user found in the database? Look for the files (or sql, ldap, etc.) module result.

  • Was Auth-Type set? If none of pap, chap, mschap, eap, etc. sets it, then the user will be rejected.

Authentication

After the recv Access-Request section, the server checks whether Auth-Type was set. If it was not set, the server rejects the request immediately:

(0) No 'Auth-Type' attribute found, cannot authenticate the user - rejecting the request

In this trace, Auth-Type = pap was set, so the server runs the authenticate pap section.

(0)   Running 'authenticate pap' from file ./raddb/sites-enabled/default
(0)   authenticate pap {

The pap module compares the User-Password from the packet against the known-good password that was set earlier by the files module.

For a wrong password, you should see output similar to this:

(0)     pap - Login attempt with password
(0)     pap - Comparing with "known-good" Cleartext (5)
(0)     pap - ERROR: Cleartext password does not match "known good" password
(0)     pap (reject)
(0)   } # authenticate pap ((reject))
(0) Failed to authenticate the user

For a correct password, you should see output similar to this:

(1)     pap - Login attempt with password
(1)     pap - Comparing with "known-good" Cleartext (5)
(1)     pap - User authenticated successfully
(1)     pap (ok)
(1)   } # authenticate pap ((ok))
If the pap module returns noop in the authenticate section, that usually means no known-good password (such as control.Password.Cleartext) was set in the recv Access-Request section. Go back and check that the database module (files, sql, ldap, etc.) found the user and returned ok or updated.

Sending a reply

When the server sends a reply, it runs a send section which is named after the packet type.

Access-Reject

When authentication fails, the server runs the send Access-Reject section before sending the reply.

(0)   Running 'send Access-Reject' from file ./raddb/sites-enabled/default
(0)   send Access-Reject {
(0)     attr_filter.access_reject - Matched entry DEFAULT at line 11
(0)     attr_filter.access_reject (updated)
(0)     delay_reject - Delaying request by ~1.0s
(0)     delay_reject (noop)
(0)   } # send Access-Reject ((updated))

The attr_filter.access_reject module strips any reply attributes that are not permitted in an Access-Reject packet.

The delay_reject module (an instance of rlm_delay) delays the reply for a configurable time (default one second) before sending it to the NAS. This delay protects against brute-force dictionary attacks.

After the section finishes, the virtual server block closes and the reply is sent.

(0)   default (noop)
(0) } # default (noop)
(0) Done request
(0) Sending Access-Reject ID 104 from 0.0.0.0:1812 to 127.0.0.1:58504 length 50 via socket radius_udp server 127.0.0.1 port 1812
(0)   Reply-Message = "Hello, bob"
(0)   Packet-Type = Access-Reject
(0) Finished request

The Sending line mirrors the Received line, with the source and destination swapped to show that the server is sending the reply to the client. Any attributes in the reply are then printed.

Always check the reply attributes. If the server is sending the correct reply but the user is still not getting the expected service, the problem is in the NAS, not the server.

Access-Accept

When authentication succeeds, the server runs the send Access-Accept section. With the default configuration, the send Access-Accept section copies the user name into the reply, and then runs the various policies in order to enforce standard compliance. These policies can, of course, be edited or deleted.

(1)    Running 'send Access-Accept' from file /etc/raddb/sites-enabled/default
(1)    send Access-Accept {
(1)      reply += {
(1)        Session-State-User-Name = "bob"
(1)      }
(1)      policy remove_reply_message_if_eap {
...
(1)      } # policy remove_reply_message_if_eap (noop)
(1)    } # send Access-Accept ((noop))
(1)    default (noop)
(1)  } # default (noop)
(1)  Done request
(1)  Sending Access-Accept ID 79 from 0.0.0.0/0:1812 to 127.0.0.1:47730 length 50 via socket radius_udp server * port 1812
(1)    Reply-Message = Hello, bob
(1)    Packet-Type = Access-Accept
(1)  Finished request

No reply sent

If a send section returns handled, the server skips sending a reply entirely. This is used for EAP challenges and for policies that intentionally discard packets without a response.

Accounting packets

Accounting packets follow a similar pattern, but use recv and send section names taken from the accounting packet names.. The recv Accounting-Request section runs when the server receives an Accounting-Request packet. After that section runs, the server looks at Acct-Status-Type, and runs an accounting section named for that status type. For example, accounting Start { }. This behavior lets you configure policies which are run only when specific types of accounting messages are received.

For example, you likely want to run different policies on "Start" packets, than "Stop" packets.

Finally, the send Accounting-Response section runs before the reply is sent.

(2)  default {
(2)    Received Accounting-Request ID 123 from 127.0.0.1:42980 to 127.0.0.1:1813 via lo
...
(2)    Running 'recv Accounting-Request' from file /etc/raddb/sites-enabled/default
(2)    recv Accounting-Request {
...
(2)    } # recv Accounting-Request ((ok))
(2)    accounting Start {
(2)      ... ignoring empty subsection ...
(2)    }
(2)    Running 'send Accounting-Response' from file /etc/raddb/sites-enabled/default
(2)    send Accounting-Response {
(2)      detail (ok)
(2)      attr_filter.accounting_response - Matched entry DEFAULT at line 12
(2)      attr_filter.accounting_response (updated)
(2)    } # send Accounting-Response ((updated))
(2)    default (ok)
(2)  } # default (ok)
(2)  Done request
(2)  Sending Accounting-Response ID 123 from 0.0.0.0/0:1813 to 127.0.0.1:42980 length 20 via socket radius_udp server * port 1813
(2)    Packet-Type = Accounting-Response
(2)  Finished request

If the server stops producing output

If Ready to process requests was printed but nothing appears after that, the server is not receiving any packets. That is a network or firewall problem, not a server configuration problem. Check that the NAS is sending packets to the correct IP address and port, and that no firewall is blocking UDP on port 1812 or 1813.