Skip to content

Commit

Permalink
Update SQL counter module howto
Browse files Browse the repository at this point in the history
  • Loading branch information
ndptech committed Feb 15, 2024
1 parent ab4ad43 commit 8c0627d
Showing 1 changed file with 58 additions and 136 deletions.
194 changes: 58 additions & 136 deletions doc/antora/modules/howto/pages/modules/sqlcounter/index.adoc
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.

0 comments on commit 8c0627d

Please sign in to comment.