rediswho and Simultaneous-Use
Alan DeKok
alan.dekok at inkbridge.io
Mon Nov 17 17:02:47 UTC 2025
Catching up on email after traveling too much...
> On Oct 8, 2025, at 12:21 PM, Nitzan Tzelniker <nitzan.tzelniker at gmail.com> wrote:
> In the meantime, I considered the following implementation approach.
> Please let me know if it sounds reasonable:
>
> Session Key Structure:
> Append the Acct-Unique-Session-Id to the User-Name to form the
> Redis list name, using a separator such as : (which is invalid in
> usernames) — e.g. %{User-Name}:%{Acct-Unique-Session-Id}.
The Acct-Unique-Session-Id should be unique enough, but I understand why it needs the User-Name.
> Interim-Update Handling:
> Use LSET 0 instead of LPUSH to overwrite the existing session
> data during Interim-Update events.
Mostly, except that accounting packets can come out of order.
The session should also have a "last updated time". If the current packet Event-Timestamp (or received time - Acct-Delay-Time) is less than that, then don't change the entry in Redis.
Otherwise, update the entry, including the "last updated time".
> Stop Records:
> Use DEL on Stop packets to remove the corresponding session entry.
I wouldn't delete the records. Accounting packets can be out of order. So the "last updated time" check should catch this, too.
Records should be deleted if they're (a) closed, and (b) haven't seen an update in a day or so.
> NAS Reload Tracking:
> For Accounting-On and Accounting-Off events, create Redis keys
> with the NAS IP address and timestamp, similar to how the SQL
> nasreload mechanism works.
Yes
> Session Validation Logic (via Python script under session):
> a. The script performs Redis SCAN 0 MATCH %{User-Name}:* to find all
> active session keys for the user.
I'm not sure that a Python script is necessary. You should be able to do this in unlang.
Or, if complex queries are needed, use a Lua script which is loaded into the Redis DB.
> b. If the number of sessions returned is less than the configured
> Simultaneous-Use limit, the Access-Request is accepted.
> c. Otherwise, for each matching session key:
> Retrieve the session data using LRANGE and parse it.
> If the NAS reload timestamp is newer than the last update,
> accept the Access-Request and Redis DEL the session.
> Otherwise, run radcheck (or equivalent Python logic) to
> verify if the user is still actually logged in:
> If yes → reject the Access-Request.
> If no → accept the Access-Request and Redis DEL the
> stale session.
That should work.
> By the way, for FreeRADIUS v4.0, what is the recommended method to
> implement Simultaneous-Use, given that the checksimul functionality
> has been removed from all modules?
The unlang in v4 has enough features that you can write the simultaneous-use checks directly in unlang.
We do need to add examples of that, though. I'll add it to the list of things to do in v4.
Alan DeKok.
More information about the Freeradius-Users
mailing list