-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
58 additions
and
136 deletions.
There are no files selected for viewing
194 changes: 58 additions & 136 deletions
194
doc/antora/modules/howto/pages/modules/sqlcounter/index.adoc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,161 +1,83 @@ | ||
= rlm_sqlcounter | ||
= SQL counter module | ||
|
||
Installation and running guide by Ram Narula [email protected] Internet for Education (Thailand) | ||
== Introduction | ||
|
||
Pre-requisites: Make sure to have configured radiusd with rlm_sqlcounter installed | ||
The `sqlcounter` module provides a mechanism which can be used to enforce periodic | ||
resource limits. | ||
|
||
``` | ||
make clean ./configure –with-experimental-modules make make install | ||
``` | ||
Each instance of the module is configured with a period (e.g. daily) which is used | ||
to populate values in two attributes in the `control` list when the module is | ||
called. | ||
|
||
Make sure to have radiusd running properly under sql and there | ||
must be a `sql` entry under `recv Accounting-Request { }` section of radiusd.conf | ||
An attribute is defined to contain a "limit" for whatever resource is being counted, | ||
(e.g. session time or data volume) for the specified period. | ||
|
||
== Configuration | ||
|
||
Create a text file called sqlcounter.conf in the same directory | ||
where radiusd.conf resides (usually /usr/local/etc/raddb) with the | ||
following content (for mysql): | ||
|
||
``` | ||
sqlcounter noresetcounter { | ||
sql_module_instance = sqlcca3 | ||
counter_name = Max-All-Session-Time | ||
check_name = Max-All-Session | ||
reply_name = Session-Timeout | ||
key = User-Name reset = never | ||
query = "SELECT SUM(AcctSessionTime) FROM radacct WHERE UserName='%{%k}'" | ||
} | ||
|
||
sqlcounter dailycounter { | ||
sql_module_instance = sqlcca3 | ||
driver = rlm_sqlcounter | ||
counter_name = Daily-Session-Time | ||
check_name = Max-Daily-Session | ||
reply_name = Session-Timeout | ||
key = User-Name | ||
reset = daily | ||
query = "SELECT SUM(AcctSessionTime - GREATEST((%b - UNIX_TIMESTAMP(AcctStartTime)), 0)) FROM radacct WHERE UserName='%{%k}' AND UNIX_TIMESTAMP(AcctStartTime) + AcctSessionTime > '%b'" | ||
} | ||
|
||
sqlcounter monthlycounter { | ||
sql_module_instance = sqlcca3 | ||
counter_name = Monthly-Session-Time | ||
check_name = Max-Monthly-Session | ||
reply_name = Session-Timeout | ||
key = User-Name | ||
reset = monthly | ||
query = "SELECT SUM(AcctSessionTime - GREATEST((%b - UNIX_TIMESTAMP(AcctStartTime)), 0)) FROM radacct WHERE UserName='%{%k}' AND UNIX_TIMESTAMP(AcctStartTime) + AcctSessionTime > '%b'" | ||
} | ||
``` | ||
|
||
The respective lines for postgresql are: | ||
|
||
``` | ||
query = "SELECT SUM(AcctSessionTime) FROM radacct WHERE | ||
UserName='%{%k}'" | ||
|
||
query = "SELECT SUM(AcctSessionTime - GREATEST((%b - | ||
EXTRACT(epoch FROM AcctStartTime)), 0)) FROM radacct WHERE UserName='%{%k}' | ||
AND EXTRACT(epoch FROM AcctStartTime) + AcctSessionTime > '%b'" | ||
|
||
query = "SELECT SUM(AcctSessionTime - GREATEST((%b - | ||
EXTRACT(epoch FROM AcctStartTime)), 0)) FROM radacct WHERE UserName='%{%k}' | ||
AND EXTRACT(epoch FROM AcctStartTime) + AcctSessionTime > '%b'" | ||
``` | ||
|
||
If you are running postgres 7.x, you may not have a GREATEST function. | ||
If that attribute exists, the module will run an SQL query to calculate the used | ||
resource quantity. | ||
|
||
An example of one is: | ||
The retrieved value is then compared with the limit and if the limit has been | ||
exceeded, the module will return `reject` | ||
|
||
``` | ||
CREATE OR REPLACE FUNCTION ``greater''(integer, integer) RETURNS integer | ||
AS ’ DECLARE res INTEGER; one INTEGER := 0; two INTEGER := 0; BEGIN one | ||
= $1; two = $2; IF one IS NULL THEN one = 0; END IF; IF two IS NULL THEN | ||
two = 0; END IF; IF one > two THEN res := one; ELSE res := two; END IF; | ||
RETURN res; END; ’ LANGUAGE `plpgsql'; | ||
``` | ||
|
||
[2] Include the above file to radiusd.conf by adding a | ||
line in `modules {}` section. | ||
|
||
``` | ||
modules { | ||
|
||
$INCLUDE $\{confdir}/sqlcounter.conf | ||
``` | ||
|
||
…some other entries here… | ||
|
||
[3] Make sure to have the sqlcounter names under authorize section like | ||
the following: | ||
== Configuration | ||
|
||
``` | ||
recv Access-Request { | ||
# some entries here… …some entries here… …some entries here… …some entries here… | ||
noresetcounter | ||
dailycounter | ||
monthlycounter | ||
} | ||
``` | ||
A sample module configuration is provided in `raddb/mods-available/sqlcounter`. | ||
|
||
* noresetcounter: the counter that never resets, can be used for real | ||
session-time cumulation | ||
This includes configurations which cover daily and monthly periods, plus a | ||
couple of examples where there are no reset dates on the periods being considered. | ||
|
||
* dailycounter: the counter that resets everyday, can be used for limiting | ||
daily access time (eg. 3 hours a day) | ||
The SQL queries associated with these sample module configurations are found | ||
in `raddb/mods-config/sql/counter/<dialect>/*.conf` with each instances query | ||
in a different file. | ||
|
||
* monthlycounter: the counter that resets monthly, can be used for | ||
limiting monthly access time (eg. 50 hours per month) | ||
As provided, the counters are all based on session time, using the `acctsessiontime`, | ||
field from `radacct`. | ||
|
||
You can make your own names and directives for resetting the counter by | ||
reading the sample sqlcounter configuration in `raddb/experimental.conf` | ||
In order to enforce limits based on data volume, the queries should be updated to | ||
use the `acctinputoctets` and / or `acctoutputoctets` fields depending on the | ||
requirement. | ||
|
||
== Implementation | ||
See the sample module configuration for details of the configuration options. | ||
|
||
Add sqlcounter names to be used into radcheck or radgroupcheck table | ||
appropriately for sql. For users file just follow the example below. | ||
|
||
NOTE: The users in the example below must be able to login normally as | ||
the example will only show how to apply sqlcounter counters. | ||
|
||
Scenarios [1] username test0001 have total time limit of 15 hours (user | ||
can login as many times as needed but can be online for total time of 15 | ||
hours which is 54000 seconds) If using normal users file authentication | ||
the entry can look like: | ||
== Usage | ||
|
||
``` | ||
test0001 Max-All-Session := 54000, User-Password == `blah` | ||
Service-Type = Framed-User, Framed-Protocol = PPP | ||
``` | ||
As a prerequisite to using the `sqlcounter` module with the sample configurations | ||
an instance of the `sql` module must be configured and called when processing | ||
accounting packets. | ||
|
||
or for sql make sure to have `Max-All-Session` entry under either radcheck | ||
or radgroup check table: | ||
This instance of the `sql` module should be set as the `sql_module_instance` | ||
in the `sqlcounter` module configuration. | ||
|
||
``` | ||
INSERT into radcheck VALUES(’','test0001','Max-All-Session','54000',':='); | ||
``` | ||
Depending on how user limits are to be set, appropriate entries should be | ||
added to the relevant source data store being used to set `control` attributes | ||
during authorization. e.g. if the `sql` module is being used to hold user | ||
data, add entries to `radcheck` or `radgroupcheck` as appropriate. | ||
|
||
[2] username test0002 have total time limit of 3 hours a day | ||
The attribute to set is the one referred to in the `check_name` module, | ||
configuration, e.g. on the sample `dailycounter` module instance the attribute | ||
is `&control.Max-Daily-Session`. | ||
|
||
``` | ||
test0002 Max-Daily-Session := 10800, User-Password == 'blah' | ||
Service-Type = Framed-User, Framed-Protocol = PPP | ||
``` | ||
In the authorization policy, call the required `sqlcounter` module instance, | ||
having made sure that the appropriate `check_name` attribute is set. | ||
|
||
or in sql | ||
If the configured query returns a value which exceeds the value in the limit | ||
attribute, the module will return `reject` and populate the attribute set | ||
in `reply_message_name`. | ||
|
||
`INSERT into radcheck VALUES (’',’test0002', 'Max-Daily-Session','10800',':=');` | ||
If the retrieved value is below the limit, then the attribute set in | ||
`reply_name` will be populated in the `reply` list with the difference | ||
between the limit and the retrieved value and the module will return `updated`. | ||
|
||
[3] username test0003 have total time limit of 90 hours a month | ||
If that attribute already exists with a lower value, that value will be | ||
left and the module will return `ok`. | ||
|
||
``` | ||
test0003 Max-Monthly-Session := 324000, User-Password == ``blah'' | ||
Service-Type = Framed-User, Framed-Protocol = PPP in sql: > INSERT into | ||
radcheck VALUES (’`,’test0003',`Max-Monthly-Session',`10800',`:='); | ||
``` | ||
If no `reply_name` is configured, then the module returns `ok`. | ||
|
||
NOTE: The `Max-All-Session`, `Max-Daily-Session` and `Max-Monthly-Session` are | ||
defined in `sqlcounter.conf` | ||
For the use case where the reply attribute is being used to set a point when | ||
a user re-authenticates, specifically using time (in seconds), the option | ||
`auto_extend` can be used to avoid unnecessary re-authentications. | ||
|
||
WARNING: Accounting must be done via sql or this will not work. | ||
Setting this option to `yes` causes a check to be done to see if the difference | ||
between the configured limit and the retrieved value is sufficient to cover the | ||
time to the next period. If it is, then the value returned in the reply | ||
attribute will be the number of seconds until the next period plus the value of | ||
the limit. |