Syed Jahanzaib Personal Blog to Share Knowledge !

November 1, 2017

Mikrotik with Freeradius/mySQL – Dealing with STALE sessions in FR – Part 5

Filed under: freeradius — Tags: , — Syed Jahanzaib / Pinochio~:) @ 1:26 PM

~ Dealing with STALE session in Freeradius 2.x ~
! From the CORE of FREERADIUS !
By
Syed jahanzaib

FREERADIUS WITH MIKROTIK – Part #1

FREERADIUS WITH MIKROTIK – Part #2 

FREERADIUS WITH MIKROTIK – Part #3

FREERADIUS WITH MIKROTIK – Part #4

FREERADIUS WITH MIKROTIK – Part #5 > You are here

Part-6


Scenario:

Mikrotik as acting as NAS (pppoe server) along with Freeradius as AAA. in the event of light or hardware failure or in a situation where NAS cannot update the FR about user is being disconnected & not active any more, the FR will consider user ACTIVE in radacct table, therefore on next dialup attempt by the user (once every thing is restored), he will get access denied because

  1. There is Simltanous-Use attribute to prevent multiple login from same user
  2. user accctsoptime is NULL because FR have not receive any update from the NAS about user is not online any more.

To remove such stale sessions, there are various methods, you can make your own bash script & schedule it to run every x minutes (example every 5 minutes). Or you can use IF query in authorize session so that when user tries to reconnect & his sessions have NULL  then in this case the query should put stop entry in acctstoptime and allow user new login. or make a PHP program that can be scheuled to run every 5 minutes and then query the radacct session for users whose account update have not received from the NAS.

First you need to add lastupdate column in your RADACCT table (in radius db) . Infact all solutions posted in this guide relies on it. so add it

ALTER TABLE 'radacct' ADD 'lastupdate' TIMESTAMP NOT NULL AFTER 'xascendsessionsvrkey';

Solution#1 [Using PHP program, good if u want to encrypt your code, ELSE bash is good]

 

Create a PHP file name fr_stale.php in your /var/www (for ubuntu)

/var/www/fr_stale.php

<?php
date_default_timezone_set('Asia/Karachi');
include ("/var/www/db.php");
$check_stale = mysqli_query($db,"UPDATE `radacct` SET acctstoptime = NOW() WHERE acctstoptime IS NULL AND lastupdate < DATE_SUB(NOW(), INTERVAL 1 MINUTE)");
?>

Save & exit.

Create a database details file that will be called by above php file in order to get DB connection details.

/var/www/db.php

<?php
$db_username = 'radius';
$db_password = 'PASSWORD';
$db_name = 'radius';
$db_host = '127.0.0.1';
$db=mysqli_connect($db_host, $db_name, $db_password, $db_name);
$mysqli = new mysqli($db_host, $db_username, $db_password, $db_name);
// If unable to communicate with MYSQL, print ERROR
if ($mysqli->connect_error) {
die('Error : ('. $mysqli->connect_errno .') '. $mysqli->connect_error);
}
?>>

Schedule it in CRON

*/5 * * * * /usr/bin/php  /var/www/fr_stale.php

Solution # 3
Using BASH in CRON

You can use following bash script to run every 5 minutes which will check for any stale session by matching last update time with current.

mysql -uroot -pSQLPASS -s --skip-column-names -e "use radius; UPDATE radacct SET acctstoptime = NOW() WHERE acctstoptime IS NULL AND lastupdate < DATE_SUB(NOW(), INTERVAL 2 MINUTE)";

Solution#3
This will update the radacct acctstoptime only if user will try to re-connect, tested it in old times]

Edit /etc/freeradius/sites-enabled/default

nano /etc/freeradius/sites-enabled/default

in AUTHORIZE { section add following query

if (User-Name){
if("%{sql:UPDATE radacct set AcctStopTime=ADDDATE(AcctStartTime,INTERVAL AcctSessionTime SECOND), AcctTerminateCause='Clear-Stale Session' WHERE UserName='%{User-Name}' and CallingStationId='%{Calling-Station-Id}' and AcctStopTime is NULL}"){
}
}

Save & restart freeradius server.

This way if NAS goes out, the session will still show online in radacct table, but when user will relogin next time, his session on radacct table will update and new entry will be created.

 

Advertisements

%d bloggers like this: