Variables
Goal: To use run-time variable expansion.
Time: 15-30 minutes.
Files:
-
radiusd.conf -
etc/mods-config/files/authorize -
mods-available/detail
man page: radiusd.conf
documentation page: Dynamic expansions
There are two kinds of variables within the server. The first is within
radiusd.conf and related files. These variables are referenced via the
$ character, which is used to define common terms (e.g. ${logdir}) so that
those terms do not have to be repeated multiple times in the
configuration files. These variables are used only when the server reads
the configuration files, and they cannot be updated or edited once the files
have been read.
Below example shows variables withing radiusd.conf
prefix = /usr/local
exec_prefix = ${prefix}
sysconfdir = ${prefix}/etc
localstatedir = ${prefix}/var
sbindir = ${exec_prefix}/sbin
logdir = ${localstatedir}/log/radius
confdir = ${sysconfdir}/raddb
radacctdir = ${logdir}/radacct
The second kind of variable is a run-time variable, which is dynamically
expanded for each request received by the server. These variables are
referenced by the % character, and they may be used to pull the values of
attributes from the request to be used by a module. These variables may
also be used by one module to obtain information from another module.
detail-%Y-%m-%d
In this exercise, we cover configuration variables and some simple properties of the run-time variables. Later exercises cover additional properties of the run-time variables.
The main configuration file radiusd.conf and the module configuration
files contains a number of examples of the use of variables. For example,
the detail module (configured in mods-enabled/detail)
has a configuration entry named "filename", which by default has the
following value:
filename = ${radacctdir}/%{Net.Src.IP}/detail-%Y%m%d
The filename setting defines where FreeRADIUS stores its accounting
“detail” files and how they are named. The variable ${radacctdir}
points to the main directory where accounting files are stored, and
is defined in the radiusd.conf file.
The attribute %{Net.Src.IP} represents the IP address of the
RADIUS client (such as a NAS or access point) sending the request.
It is used to create a separate subdirectory for each client, so that
each client’s logs are kept separate. The detail-%Y-%m-%d part
specifies the naming pattern for the files using date formatting,
where %Y represents the year (e.g., 2026), %m represents the month
(e.g., 01), and %d represents the day (e.g., 16).
This structure ensures that logs are organized by client and date for easier management.
The configuration entry is composed of two kinds of variable expansion.
One references the ${radacctdir} configuration variable, which was
previously defined in radiusd.conf. The following variables are
expanded at run time and depend on information in the request packet
and other dynamically calculated data.
Start the server in debugging mode (radiusd -X).
In the server output, look for the detail module and the filename
configuration entry for that module. Verify that the string printed
for the filename does not print the reference to the ${radacctdir}
variable, but instead has substituted the value of that variable.
Verify also that the values of the run-time variables have not
been substituted and that they are still printed as variables.
In the server output, look for the detail module and its filename configuration. You should see something like this:
(0) detail - /usr/local/var/log/radius/radacct/%{Net.Src.IP}/detail-%Y-%m-%d expands to /usr/local/var/log/radius/radacct/127.0.0.1/detail-2026-1-16
(0) detail (ok)
If you don’t see any configuration printed for the detail file module
ensure it is uncommented in the accounting {} section of the
sites-available/default virtual server.
accounting Stop {
detail
}
You can go to the dynamic expansion
documentation to determine the meaning of the variables used in the filename configuration entry.
Then, end the server an accounting packet and go look for the detail file, which will be
dynamically created. Verify that the contents of the file are the
accounting packet you just sent.
Execute the following command to test detail file :
echo 'User-Name = "bob"
Acct-Status-Type = Start
Acct-Session-Id = "01020304"
NAS-IP-Address = 127.0.0.1
NAS-Port = 501
NAS-Port-Type = Virtual
Service-Type = Framed-User
Framed-Protocol = PPP
Framed-IP-Address = 192.168.100.55' | radclient -x 127.0.0.1:1813 acct testing123
Use the following path to view the detail log file for the client:
etc/usr/local/var/log/radius/radacct/127.0.0.1/detail-2026-1-16
The detail logs show detailed RADIUS request information and can be found in the accounting log directory.
Fri Jan 16 06:52:27 2026
User-Name = "bob"
Acct-Status-Type = ::Start
Acct-Session-Id = "01020304"
NAS-IP-Address = 127.0.0.1
NAS-Port = 501
......................
Packet-Type = ::Accounting-Request
Event-Timestamp = "2026-01-16T06:52:27Z"
Acct-Unique-Session-Id = "c52ad9a77a79d468c639eb9ddbad9cea"
Timestamp = 1768546347
In addition to being used in the configuration files, run-time variables may also be used to create values for reply attributes. Stop the server, and edit the users file to add the following entry at the top:
bob Password.Cleartext := "hello"
Reply-Message = "Hello %{User-Name}, your NAS port is %{NAS-Port}",
Reply-Message += "at time %T"
Start the server, and send the authentication packet. Verify that the
Reply-Message attributes contain the user name, NAS port, time from the reply
echo 'User-Name = "bob"
User-Password = "hello"
NAS-IP-Address = 127.0.0.1
NAS-Port = 501
NAS-Port-Type = Virtual' | radclient -x 127.0.0.1:1812 auth testing123
Received Access-Accept Id 151 from 127.0.0.1:1812 to 0.0.0.0:46176 via lo length 109
Message-Authenticator = 0x6b0ff2f6cb09cba3683d677d300a46b9
Reply-Message = "Hello bob, your NAS port is 501"
Reply-Message = "at time 2026-01-16T08:20:14.-43"
User-Name = "bob"
Questions
-
Why are run-time variables useful?
-
How would you configure that entry in the file to reply with the directory name where the
radiusd.conffile is stored? Why is this a bad idea? -
How would you create an entry in the users file that matched users when their
Classwas the same as theirNAS-Port?