UPDATED 2021 -Limiting Simultaneous Sessions
Why implement it
If you are driven by sales of vouchers, limiting the amount of people who can use the voucher at one time can result in more sales.
If you are very strict on limiting the amount of data a user can use, it is wise to restrict the sessions even to only one in order to ensure accurate data cap calculations.
There is a catch
You might get more support calls since it may just happen that a person was connected through the captive portal and got disconnected.
The back-end still thinks he is connected.
If the person then tries to connect again and there is a limit on the sessions to e.g. 1, he will not be able to connect again.
Usually there is a reply attribute called Idle-Timeout which you can set to a low value to auto-disconnect the user from the Captive Portal's side when there is no data flow.
Another option is to let the Back-end auto close stale sessions by editing the Dynamic Client under RADIUS menu and go to Dynamic Client → Enhancements and select Auto Close Stale Sessions with a time.
These items are just a heads-up before you implement this limit.
Check if enabled
vi /etc/freeradius/3.0/mods-config/sql/main/mysql/queries.conf
#######################################################################
# Simultaneous Use Checking Queries
#######################################################################
# simul_count_query - query for the number of current connections
# - If this is not defined, no simultaneous use checking
# - will be performed by this module instance
# simul_verify_query - query to return details of current connections
# for verification
# - Leave blank or commented out to disable verification step
# - Note that the returned field order should not be changed.
#######################################################################
simul_count_query = "\
SELECT COUNT(*) \
FROM ${acct_table1} \
WHERE username = '%{SQL-User-Name}' \
AND acctstoptime IS NULL"
#simul_verify_query = "\
# SELECT \
# radacctid, acctsessionid, username, nasipaddress, nasportid, framedipaddress, \
# callingstationid, framedprotocol \
# FROM ${acct_table1} \
# WHERE username = '%{SQL-User-Name}' \
# AND acctstoptime IS NULL"
#20.04
service freeradius stop
service freeradius start
Applying the limit
You can also add this to a Profile Component
See the limit in action