A modern Python toolkit for building RADIUS clients and servers.
pyrad2 gives you the protocol - packet encoding, dictionary parsing, transport handling, retransmission, TLS - so you can write the business logic. Build an authentication backend, a CoA proxy, a RadSec accounting collector, or a network-access controller without touching wire formats.
📚 Full documentation: nicholasamorim.github.io/pyrad2
pip install pyrad2 # or: uv add pyrad2Requires Python 3.12+.
from pyrad2.client_async import ClientAsync
from pyrad2.dictionary import Dictionary
from pyrad2.constants import PacketType
client = ClientAsync(server="radius.example.com", secret=b"...", dict=Dictionary("dictionary"))
await client.initialize_transports(enable_auth=True)
req = client.create_auth_packet(User_Name="alice", User_Password="hunter2")
reply = await client.send_packet(req)
if reply.code == PacketType.AccessAccept:
print("Welcome,", reply["User-Name"][0])Head to the Getting Started guide for the full walkthrough.
| Feature | Spec |
|---|---|
| RADIUS client & server (sync + async) | RFC 2865 |
| RadSec - RADIUS over TLS | RFC 6614 |
| RADIUS/1.1 over RadSec (experimental) | RFC 9765 |
| CoA & Disconnect (Dynamic Authorization) | RFC 5176 |
| Status-Server health checks | RFC 5997 |
| Duplicate detection / response cache | RFC 5080 §2.2.2 |
| FreeRADIUS dictionary support | Extended attributes, vendor formats, EVS |
| Wire-level packet tracing | PYRAD2_TRACE=1 |
pyrad2 is a library, not a daemon. It is not a drop-in replacement for FreeRADIUS; it gives you the moving parts to build your own.
Two complementary surfaces ship with the repo:
scenarios/- single-process, end-to-end demos. A server and a client run in the same event loop so the full exchange shows up on one log. Don't edit them - they're runnable explanations.examples/- operational scripts you copy into your project and edit.
make demo # all scenarios sequentially
make scenario_auth # Access-Request → Access-Accept (UDP)
make scenario_acct # Accounting-Request → Accounting-Response
make scenario_coa # CoA-Request → CoA-ACK (RFC 5176)
make scenario_status # Status-Server health check (RFC 5997)
make scenario_dedup # Duplicate detection (RFC 5080)
make scenario_radsec # RadSec over mutual TLS (RFC 6614)
make scenario_radsec_v11 # RADIUS/1.1 over RadSec (RFC 9765)Watch the actual bytes on the wire by setting PYRAD2_TRACE=1 on any script:
PYRAD2_TRACE=1 make scenario_auth- Getting Started - install, RADIUS in one minute, run an exchange
- Running a Server - auth, accounting, CoA, RadSec, RADIUS/1.1
- Making Requests - clients, EAP, health checks, RadSec
- Dictionary Reference - every supported type and option
- Migrating from pyrad - breaking changes since 2.0
make testpyrad2 is currently maintained by Nicholas Amorim.
pyrad was written by Wichert Akkerman and is maintained by Christian Giese (GIC-de) and Istvan Ruzman (Istvan91).
This project is licensed under a BSD license. Copyright and license information can be found in LICENSE.txt.
Bugs and wishes can be submitted in the pyrad2 issue tracker on GitHub. PRs are very welcome.
