Capture RADIUS Attributes from a pppd Link
The radattr plugin gets pppd to dump every RADIUS-returned attribute into a per-interface file, ready for your ip-up or ip-down scripts to read. Handy when a hook needs a server-supplied value and you would rather not stand up a second RADIUS client to get at it.
The route
Jump straight to the step you need, or tick off Done means at the end.
Fifteen minutes if RADIUS authentication is already working here. The examples assume Debian or Ubuntu packaging, the installed ppp package version 2.4.9-1+1.1ubuntu4, and an interface named something like ppp0. The plugin itself never creates a connection or configures RADIUS; it only watches one that already exists.
1. Check the existing RADIUS setup
Confirm the package is installed and the plugins are actually present before touching anything else. This is a read-only check:
dpkg-query -W -f='${Package} ${Version}\n' ppp
dpkg -L ppp | grep -E '/(radius|radattr)\.so$'
Expected output gives you the package version plus paths for radius.so and radattr.so. The plugin directory is package-specific, so do not hard-code a path copied from another host.
Checkpoint
The existing RADIUS plugin has to work before you bolt on attribute capture. If authentication is not already succeeding, fix that separately with pppd-radius(8) and the radiusclient configuration first. radattr does not replace /etc/radiusclient/radiusclient.conf, it just rides alongside it.
2. Add the plugins in the required order
Add both plugin lines to the pppd invocation or the peer file it uses. Order matters here: load radius.so first, then radattr.so, because the second depends on symbols the first provides.
plugin radius.so
plugin radattr.so
If the connection is started with a peer definition, place these lines with its other pppd options. If it is started by a service or another manager, change the source that actually builds the pppd command rather than testing an unrelated shell command. A typical command-line shape is:
sudo pppd call <peer-name> plugin radius.so plugin radattr.so
The command above starts or restarts a link and may alter routes, authentication state and service availability. Do not run it on a production link until you have a maintenance window and a recovery path. Preserve the current peer file before editing it:
sudo cp --preserve=mode,ownership /etc/ppp/peers/<peer-name> /etc/ppp/peers/<peer-name>.before-radattr
Checkpoint
Inspect the effective configuration before bringing up the link. You should see both plugin options, with radius.so before radattr.so.
3. Establish one test connection
Bring the link up through whatever mechanism normally manages it, and keep the pppd log open in another window. A missing plugin or the wrong load order shows up there, not in a later file check.
Once authentication completes, find the interface name:
ip -o link show | awk -F': ' '$2 ~ /^ppp[0-9]+$/ {print $2}'
For an interface named ppp0, the expected capture file is /var/run/radattr.ppp0. The manpage calls the name pppN: it is the actual PPP interface name, not a literal filename suffix to copy unchanged.
Do not create or edit this file by hand. It is runtime state owned by the plugin and may be replaced when the link is re-established.
4. Verify the captured attributes
Read the file with elevated privileges only if its permissions actually require it:
sudo test -r /var/run/radattr.ppp0 && sudo sed -n '1,120p' /var/run/radattr.ppp0
Successful output consists of one returned attribute per line, in the form Attribute-Name Attribute-Value. The exact lines depend on the RADIUS server response. An empty or absent file does not prove that the plugin loaded: check the interface name, authentication log and plugin order first.
Use these checks without displaying values if the attributes may contain sensitive network or identity data:
sudo test -s /var/run/radattr.ppp0
sudo wc -l /var/run/radattr.ppp0
The first command is successful only when the file exists and is non-empty. The second reports how many attribute lines were captured. Keep the file out of general-purpose logs and do not paste its contents into tickets until you have removed secrets and personal data.
5. Use the file from PPP hooks
The format exists for /etc/ppp/ip-up and /etc/ppp/ip-down to consume. Have those hooks work out the right file for the interface rather than assuming ppp0 forever. A minimal read-only fragment taking the interface name as its first argument looks like this:
#!/bin/sh
iface=$1
attrs=/var/run/radattr."$iface"
if [ -r "$attrs" ]; then
while IFS= read -r attribute; do
logger --tag ppp-radattr -- "$iface $attribute"
done < "$attrs"
fi
Treat this only as a shape for your hook. Logging every attribute may disclose account, addressing or policy information, so reduce it to the specific attribute your workflow needs. Quote the interface-derived path and validate any value before using it in a command, route change or filename. A hook that fails should not tear down a working link unless that is an explicit operational requirement.
Run hooks with the privileges supplied by pppd. Do not make the runtime file world-readable just to avoid using the existing privilege boundary.
6. Diagnose the common traps
Most problems trace back to one of five habits:
- Only
radattr.sois loaded: this plugin depends on symbols defined byradius.so. Load the RADIUS plugin first in the same pppd configuration. - The wrong interface is checked: use the current PPP interface name and look for the matching
/var/run/radattr.pppNfile. Interface numbers can change between connections. - RADIUS works but no useful lines appear: radattr records attributes returned at authentication time. It cannot invent attributes that the server did not return.
- A hook sees stale data: treat the file as connection-specific runtime state. Read it after the link is up, and do not cache it after the link goes down.
- A restart breaks networking: restore the saved peer file, stop the test connection through its normal manager, and re-establish the previously working configuration. The backup created in step 2 is the undo point.
Done means
radius.soandradattr.soare enabled in that order.- A controlled test authentication completes on the intended PPP link.
- The matching
/var/run/radattr.pppNfile exists and contains one attribute per line. - Any PPP hook reads the interface-specific file, limits what it logs, and validates values before acting on them.
- The original peer configuration and a safe recovery path are available.