Firstly, thank you Dirk for such a useful piece of software.
I just started exploring it's features and I have two questions as to whether some functionality exists or I have misconfigured RadiusDesk.
Q1
Say I have a data cap plan of 10Mb (Rd-Data-Total:=10000000) with a monthly reset, I have set the reply attribute 'Acct-Interim-Interval:=120', and I get those accounting updates in the radius log.
When a logged in user exceeds the 10Mb quota I would expect the user to be kicked off.
If the user logs off and logins they get a Reject Response because the quota is exceeded, which is expected behaviour.
My NAS understands COA/POD packets and I have tested it with the 'kick user off' function in the Activity Monitor dialog.
Do I need to configure something else to ensure a logged in user is kicked off when Rd-Data-Total is exceeded?
Q2
Following on from the last question, how do I set it up so that when a user is kicked off for exceeding the quota, instead of totally rejecting them I would like to instead reply with reduced WISPr-Bandwidth-Up/Down values to throttle the account until the monthly reset comes around.
Edit:
It seems one way to throttle the speed for a user that has exceed a quota is to modify check_usage_data.pl in the following way
sub authorise {
...
if($RAD_CHECK{'Rd-Avail-Data'} <= 0){
if($RAD_CHECK{'Rd-Reset-Type-Data'} ne 'never'){
#$RAD_REPLY{'Reply-Message'} = "Maximum $RAD_CHECK{'Rd-Reset-Type-Data'} usage exceeded";
$RAD_REPLY{'WISPr-Bandwidth-Max-Down'} = 400000;
$RAD_REPLY{'WISPr-Bandwidth-Max-Up'} = 200000;
$RAD_REPLY{'Reply-Message'} = "Maximum usage exceeded - Service is now slowed and will reset on day $RAD_CHECK{'Rd-Reset-Day'} of month ";
}else{
$RAD_REPLY{'Reply-Message'} = "Maximum usage exceeded";
}
#return RLM_MODULE_REJECT;
return RLM_MODULE_UPDATED;
}
...
This snip is rough and ready just for testing. To make it more configurable I could add two new attributes; Rd-Throttled-Up and Rd-Throttled-Down and test those attributes exist before splitting down the default code path or the new feature path. Would this be a useful patch to contribute?
Thanks
Last edit: Robert Gratwick 2014-09-03
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Answer to the first Q. You can do a 'Test RADIUS' when selecting the user / voucher and see the exact reply attributes that the FreeRADIUS gives back to the NAS after successful authentication.
Confirm that:
1.) The required attributes are in fact returned in the dummy test.
2.) Your NAS do actually listen and support those attributes with it's RADIUS implementation.
3.) If you use a NAS like PF-Sense they (last time I checked) do not support some reply attributes. This is why you have to configure it to 're-auth' in the background to cut a user off once the profile's cap was reached.
The second Q was discussed or queried previously. Your rough take in it is definately in the right direction.
The only thing will be to force a disconnect or kick off a COA.... that can be a bit tricky....
Let us know what you find.
Cheers
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks for the heads up on the Radius Client test feature.
To clarify my equipment. I'm using a Ubiquiti EdgeMax as my NAS and I have tested that it responds as expected to an Acct-Interim-Interval reply attribute and disconnect COA packets.
Taking a step back to simplify the problem.
How do I get check attributes like Rd-Total-Data and Rd-Reset-Type-Data to be sourced for use in the accounting section.
in /etc/raddb/sites-available/default I add a call to my test function in the accounting section
accounting {
...
RADIUSdesk_acct_kick
...
}
in /etc/raddb/policy.conf I add my test function
RADIUSdesk_acct_kick {
pl_reset_time_for_data
if(update){
if("%{control:Rd-Avail-Data}" <= 0){
# do nothing yet just check the log to see if Rd-Avail-Data is resolved
}
}
}
in reset_time_fordata.pl I add an accounting subroutine
In regard to the kick feature, I have tested something like this with success but it's messy, so I was trying to encapsulate the dogs breakfast in the 'if' statement into a module.
accounting {
...
if("%{sql:select value from radgroupcheck where attribute='Max-Octets' and groupname= (SELECT groupname FROM radusergroup WHERE username = '%{User-Name}' ORDER BY priority limit 1)}" <= "%{sql:SELECT (SUM(AcctInputOctets)+(AcctOutputOctets)) FROM radacct WHERE UserName='%{User-Name}'}"){
#user is over quota
#send disconnect
update disconnect {
User-Name = "%{User-Name}"
Acct-Session-Id = "%{Acct-Session-Id}"
NAS-IP-Address = "%{NAS-IP-Address}"
}
}
..
}
So what's the trick to sourcing the user check attributes within the accounting section?
Cheers
Robert
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
On the COA in the accounting I'll have to come back to you, but as far as i recall it is not that simple to fetch the auth detail in the acct section since FreeRADIUS sort of does it behind the scenes (differently for each one).
Cheers
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
In summary the Egdemax has two issues; it has a 2Gb (32bit) limit on the size of the Session-Octets-Limit attribute, and it doesn't send an Accounting Stop packet when the limit is exceeded. So I can't use that attribute.
Maybe I'm going about this the wrong way. Others must have come across the problem of a users quota being exceeded in a session, and as long as they don't log off they can continue forever at the same bandwidth.
It would be interesting to know how Freeradius does get the auth details behind the scenes.
I keep searching, maybe post to the Freeradius list. Gulp ;-)
Robert
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The setup below will kick a user off if quota is exceeded after receiving an Accounting update packet and throttle the users bandwidth on subsequent logins until the roll-over reset period.
I'm using a Ubiquiti Edgemax as my NAS. See the various threads above as to how I got to this point for more background.
To start
1. Data usage profile component needs two new check attributes configured; Rd-Throttled-Up and Rd-Throttled-Down.
2. User needs a new private check attribute; Rd-Throttled.
3. Data usage or bandwidth profile component needs a Acct-Interim-Interval reply attribute set.
4. When creating a plan(User-Profile) component ensure the bandwidth profile component has a high priority than the Data cap profile component. (eg 100, 80)
I initially went down the track of trying to source all the users attributes for use in the accounting section.
However I couldn't workout how to do that, I later determined that it would perhaps not be very efficient to source all of the users attributes every Acct-Interim-Internal period for each user.
In the code below I just query for the attributes I need.
Improvements
SQL querys are not my strength, I'm sure this can be improved.
In check_usage_data.pl I do something a bit odd, I use $RAD_CHECK{'Rd-Throttled'} as a return variable.
Instead of sending a COA disconnect I could send an update.
It's my first play with Freeradius/RaduisDesk and I may have missed some key concepts and best practices along the way. As a first-cut this achieves what I need for now. Any pointers will be gladly accepted.
Dirk, you may incorporate any of this into RadiusDesk, if it's useful.
Add three new attributes to dictionary
/etc/raddb/dictionary
ATTRIBUTE Rd-Throttled-Down 3147 integer #user private attribute, when throttled this is the down bandwidth
ATTRIBUTE Rd-Throttled-Up 3148 integer #user private attribute, when throttled this is the up bandwith
ATTRIBUTE Rd-Throttled 3149 integer #user private attribute -set to 1 if user is throttled, 0 not throttled
/etc/raddb/policy.conf
RADIUSdesk_acct_kick {
# if it's already slowed don't both to check anymore
if("%{sql:Select value from radcheck where attribute='Rd-Throttled' and username= '%{User-Name}'}" == 0){
# source attributes for use in reset_time_for_data.pl
update control {
Rd-Reset-Type-Data := "%{sql:Select value from radgroupcheck where attribute='Rd-Reset-Type-Data' and groupname=(select groupname from radusergroup where username=(SELECT value FROM radcheck WHERE attribute='User-Profile' and username = '%{User-Name}' limit 1) order by priority limit 1)}"
Rd-Reset-Day := "%{sql:Select value from radcheck where attribute='Rd-Reset-Day' and username = '%{User-Name}'}"
}
# works out Rd-Start-Time for Rd-Used-Data query below
pl_reset_time_for_data
update control {
Rd-Total-Data := "%{sql:Select value from radgroupcheck where attribute='Rd-Total-Data' and groupname=(select groupname from radusergroup where username=(SELECT value FROM radcheck WHERE attribute='User-Profile' and username = '%{User-Name}' limit 1) order by priority limit 1)}"
Rd-Used-Data := "%{sql:SELECT IFNULL(SUM(acctinputoctets - GREATEST((%{control:Rd-Start-Time} - UNIX_TIMESTAMP(acctstarttime)), 0))+ SUM(acctoutputoctets -GREATEST((%{control:Rd-Start-Time} - UNIX_TIMESTAMP(acctstarttime)), 0)),0) FROM radacct WHERE username='%{request:User-Name}' AND UNIX_TIMESTAMP(acctstarttime) + acctsessiontime > '%{control:Rd-Start-Time}'}"
}
# work out amount used, amount in plan, find difference
pl_check_usage_data
if(update){
if(control:Rd-Avail-Data <= 0){
update disconnect {
User-Name = "%{User-Name}"
Acct-Session-Id = "%{Acct-Session-Id}"
NAS-IP-Address = "%{NAS-IP-Address}"
}
}
}
}
...
RADIUSdesk_data_counter {
...
#Now we know how much they are allowed to use and the usage.
pl_check_usage_data
if("%{control:Rd-Throttled}" == 1){
"%{sql:update `radcheck` set value= 1 where username='%{User-Name}' and attribute='Rd-Throttled'}"
}
else{
"%{sql:update `radcheck` set value= 0 where username='%{User-Name}' and attribute='Rd-Throttled'}"
}
}
/etc/raddb/reset_time_for_data.pl
subaccounting{if($RAD_CHECK{'Rd-Reset-Type-Data'}=~ /never/i){#Return immediately returnRLM_MODULE_NOOP;}if($RAD_CHECK{'Rd-Reset-Type-Data'}=~ /monthly/i){$RAD_CHECK{'Rd-Start-Time'}=start_of_month()}if($RAD_CHECK{'Rd-Reset-Type-Data'}=~ /weekly/i){$RAD_CHECK{'Rd-Start-Time'}=start_of_week()}if($RAD_CHECK{'Rd-Reset-Type-Data'}=~ /daily/i){$RAD_CHECK{'Rd-Start-Time'}=start_of_day()}#Add a dynamic reset interval where the start time will be now minus the intervalif($RAD_CHECK{'Rd-Reset-Type-Data'}=~ /dynamic/i){my$dyn_start=dynamic_start();if($dyn_start!=0){$RAD_CHECK{'Rd-Start-Time'}=$dyn_start;}}if(exists($RAD_CHECK{'Rd-Start-Time'})){returnRLM_MODULE_UPDATED;}else{returnRLM_MODULE_NOOP;}}
/etc/raddb/check_usage_data.pl
subauthorize{...if($RAD_CHECK{'Rd-Avail-Data'} <= 0){if(exists($RAD_CHECK{'Rd-Throttled-Up'}) && exists($RAD_CHECK{'Rd-Throttled-Down'})){$RAD_REPLY{'WISPr-Bandwidth-Max-Down'} = $RAD_CHECK{'Rd-Throttled-Down'};$RAD_REPLY{'WISPr-Bandwidth-Max-Up'} = $RAD_CHECK{'Rd-Throttled-Up'};$RAD_REPLY{'Reply-Message'} = "Maximum usage exceeded - Service is now slowed and will reset on day $RAD_CHECK{'Rd-Reset-Day'} of month "; $RAD_CHECK{'Rd-Throttled'} = 1; # odd bit, I just need to return some flag, this is not setting the Rd-Throttled attribute here, that's done in policy.conf returnRLM_MODULE_UPDATED;}else{if($RAD_CHECK{'Rd-Reset-Type-Data'} ne 'never'){$RAD_REPLY{'Reply-Message'} = "Maximum $RAD_CHECK{'Rd-Reset-Type-Data'} usage exceeded";}else{$RAD_REPLY{'Reply-Message'} = "Maximum usage exceeded";}returnRLM_MODULE_REJECT;}}#Ifinsidequotaunsetslowedcheckflag$RAD_CHECK{'Rd-Throttled'} = 0;#SettheRd-Tmp-Avail-Dataifitisnotalreadyset...}subaccounting{if(exists($RAD_CHECK{'Rd-Total-Data'}) && exists($RAD_CHECK{'Rd-Used-Data'})){$RAD_CHECK{'Rd-Avail-Data'} = $RAD_CHECK{'Rd-Total-Data'} - $RAD_CHECK{'Rd-Used-Data'};returnRLM_MODULE_UPDATED;}else{returnRLM_MODULE_NOOP;}}
/etc/raddb/default
accounting {
...
RADIUSdesk_acct_kick
...
}
Setup COA disconnect
/etc/raddb/sites-available/originate-coa
home_server edgemax_coa {
type = coa
ipaddr = 10.8.0.18
port = 3799
secret = testing123
coa {
irt = 2
mrt = 16
mrc = 5
mrd = 30
}
}
...
home_server_pool coa {
type = fail-over
# Point to the CoA server above.
#home_server = localhost-coa
home_server = edgemax_coa
...
Sym. link
cd /etc/raddb/sites-enabled
sudo ln -s /etc/raddb/sites-available/originate-coa originate-coa
Debugging tips for beginners ...me
Test your NAS does something with disconnect packets
echo "User-Name=user.name" | radclient -r 1 10.8.0.18:3799 disconnect "testing123"
On NAS 'tail -f /var/log/pppoe-radius-disconnect.log'
'radtest user.name password localhost 0 testing123' is useful to see response packets
(eg is it slowed when quota is exceeded and if it switches back to normal)
'radclient localhost auto testing123 -f acct_update.txt' is useful to send accounting packets.
Read Dirks book "Freeradius Beginners guide"
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi Robert, Thank you very much for your sharing and you solved the question that i always look for. But i did a small modification:
Rd-Total-Data := "%{sql:Select value from radgroupcheck where attribute='Rd-Total-Data' and groupname=(select groupname from radusergroup where username=(SELECT value FROM radcheck WHERE attribute='User-Profile' and username = '%{User-Name}' limit 1) order by priority limit 1)}"
to
Rd-Total-Data := "%{sql:Select value from radcheck where attribute='Rd-Total-Data' and username='%{request:User-Name}'}"
reason is Rd-Total-Data is user based which is in radcheck. radgroupcheck return null to me.
Next,
I integrate this concept to topup concept. Which when your quota is finish, coa will a kick you out. next login you will get throttled speed. Then, if you top your quota, you will be kick out again. To refresh your speed.
Due to quota counter reason, when you are in throttled speed. the account in sql is not recorded.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Am using a Mikrotik Routerboard RB 3011 as my NAS. When the data is capped, the user connects and when the data allocation gets used up, the user is not being disconnected.
Please assist
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Firstly, thank you Dirk for such a useful piece of software.
I just started exploring it's features and I have two questions as to whether some functionality exists or I have misconfigured RadiusDesk.
Q1
Say I have a data cap plan of 10Mb (Rd-Data-Total:=10000000) with a monthly reset, I have set the reply attribute 'Acct-Interim-Interval:=120', and I get those accounting updates in the radius log.
When a logged in user exceeds the 10Mb quota I would expect the user to be kicked off.
If the user logs off and logins they get a Reject Response because the quota is exceeded, which is expected behaviour.
My NAS understands COA/POD packets and I have tested it with the 'kick user off' function in the Activity Monitor dialog.
Do I need to configure something else to ensure a logged in user is kicked off when Rd-Data-Total is exceeded?
Q2
Following on from the last question, how do I set it up so that when a user is kicked off for exceeding the quota, instead of totally rejecting them I would like to instead reply with reduced WISPr-Bandwidth-Up/Down values to throttle the account until the monthly reset comes around.
Edit:
It seems one way to throttle the speed for a user that has exceed a quota is to modify check_usage_data.pl in the following way
This snip is rough and ready just for testing. To make it more configurable I could add two new attributes; Rd-Throttled-Up and Rd-Throttled-Down and test those attributes exist before splitting down the default code path or the new feature path. Would this be a useful patch to contribute?
Thanks
Last edit: Robert Gratwick 2014-09-03
Here's my attempt at solving my first question.
To check if quota is exceeded on accounting updates and kick the user.
/etc/raddb/sites-avaiable/default
/etc/raddb/policy.conf
The output log shows I'm not getting past first base, the control attributes are not evaluating to anything
Any hints to solve this problem?
Hi Robert,
I have to answer before my PM nap......
Answer to the first Q. You can do a 'Test RADIUS' when selecting the user / voucher and see the exact reply attributes that the FreeRADIUS gives back to the NAS after successful authentication.
Confirm that:
1.) The required attributes are in fact returned in the dummy test.
2.) Your NAS do actually listen and support those attributes with it's RADIUS implementation.
3.) If you use a NAS like PF-Sense they (last time I checked) do not support some reply attributes. This is why you have to configure it to 're-auth' in the background to cut a user off once the profile's cap was reached.
The second Q was discussed or queried previously. Your rough take in it is definately in the right direction.
The only thing will be to force a disconnect or kick off a COA.... that can be a bit tricky....
Let us know what you find.
Cheers
Hi Dirk,
Thanks for the heads up on the Radius Client test feature.
To clarify my equipment. I'm using a Ubiquiti EdgeMax as my NAS and I have tested that it responds as expected to an Acct-Interim-Interval reply attribute and disconnect COA packets.
Taking a step back to simplify the problem.
How do I get check attributes like Rd-Total-Data and Rd-Reset-Type-Data to be sourced for use in the accounting section.
in /etc/raddb/sites-available/default I add a call to my test function in the accounting section
in /etc/raddb/policy.conf I add my test function
in reset_time_fordata.pl I add an accounting subroutine
This is the result in the log
you see the noop because $RAD_CHECK{'Rd-Total-Data'} etc don't resolve
just to check the idea works, I hardcode a Rd-Avail-Data value in accounting
logfile
Here you see a real value is returned.
In regard to the kick feature, I have tested something like this with success but it's messy, so I was trying to encapsulate the dogs breakfast in the 'if' statement into a module.
So what's the trick to sourcing the user check attributes within the accounting section?
Cheers
Robert
Hi Robert,
I've did a bit of googleing on the Edgemax and it seems this page list the supported AVPs
https://community.ubnt.com/t5/EdgeMAX-Updates-Blog/EdgeMax-software-release-v1-3-0/ba-p/591711
You thus have to ensure that your counter reply with a value for:
Session-Octets-Limit
In order to enforce the cap on the session.
Here's a bit more on the counters:
http://www.radiusdesk.com/technical_discussions/principle_profile
On the COA in the accounting I'll have to come back to you, but as far as i recall it is not that simple to fetch the auth detail in the acct section since FreeRADIUS sort of does it behind the scenes (differently for each one).
Cheers
Hi Dirk,
the page regarding priciple profile is missing from technical discussion page.
Fabrizio
Hi Dirk,
Yes the Session-Octets-Limit is a good idea but ... http://community.ubnt.com/t5/EdgeMAX/EdgeMax-not-sending-Accounting-stop-packet-when-using-Session/m-p/972527#M39828
In summary the Egdemax has two issues; it has a 2Gb (32bit) limit on the size of the Session-Octets-Limit attribute, and it doesn't send an Accounting Stop packet when the limit is exceeded. So I can't use that attribute.
Maybe I'm going about this the wrong way. Others must have come across the problem of a users quota being exceeded in a session, and as long as they don't log off they can continue forever at the same bandwidth.
It would be interesting to know how Freeradius does get the auth details behind the scenes.
I keep searching, maybe post to the Freeradius list. Gulp ;-)
Robert
The setup below will kick a user off if quota is exceeded after receiving an Accounting update packet and throttle the users bandwidth on subsequent logins until the roll-over reset period.
I'm using a Ubiquiti Edgemax as my NAS. See the various threads above as to how I got to this point for more background.
To start
1. Data usage profile component needs two new check attributes configured; Rd-Throttled-Up and Rd-Throttled-Down.
2. User needs a new private check attribute; Rd-Throttled.
3. Data usage or bandwidth profile component needs a Acct-Interim-Interval reply attribute set.
4. When creating a plan(User-Profile) component ensure the bandwidth profile component has a high priority than the Data cap profile component. (eg 100, 80)
I initially went down the track of trying to source all the users attributes for use in the accounting section.
However I couldn't workout how to do that, I later determined that it would perhaps not be very efficient to source all of the users attributes every Acct-Interim-Internal period for each user.
In the code below I just query for the attributes I need.
Improvements
SQL querys are not my strength, I'm sure this can be improved.
In check_usage_data.pl I do something a bit odd, I use $RAD_CHECK{'Rd-Throttled'} as a return variable.
Instead of sending a COA disconnect I could send an update.
It's my first play with Freeradius/RaduisDesk and I may have missed some key concepts and best practices along the way. As a first-cut this achieves what I need for now. Any pointers will be gladly accepted.
Dirk, you may incorporate any of this into RadiusDesk, if it's useful.
Add three new attributes to dictionary
/etc/raddb/dictionary
/etc/raddb/policy.conf
/etc/raddb/reset_time_for_data.pl
/etc/raddb/check_usage_data.pl
/etc/raddb/default
Setup COA disconnect
/etc/raddb/sites-available/originate-coa
Sym. link
Debugging tips for beginners ...me
Test your NAS does something with disconnect packets
echo "User-Name=user.name" | radclient -r 1 10.8.0.18:3799 disconnect "testing123"
On NAS 'tail -f /var/log/pppoe-radius-disconnect.log'
'radtest user.name password localhost 0 testing123' is useful to see response packets
(eg is it slowed when quota is exceeded and if it switches back to normal)
'radclient localhost auto testing123 -f acct_update.txt' is useful to send accounting packets.
Read Dirks book "Freeradius Beginners guide"
Hi Robert,
Sometimes it is good when one is slow to answer on the forum. It forces people to invent creative solutions!
Someone was just asking today about if this is possible.
Many many thanks for sharing this with the community. I'm sure more will have a use for this.
As time permits I'll definitely use this as the content of a Technical discussion page on the RADIUSdesk website.
....I suppose the fear of getting a tongue-lashing can also be a way to become creative ;-)!!!
Cheers
Hi Robert, Thank you very much for your sharing and you solved the question that i always look for. But i did a small modification:
Rd-Total-Data := "%{sql:Select value from radgroupcheck where attribute='Rd-Total-Data' and groupname=(select groupname from radusergroup where username=(SELECT value FROM radcheck WHERE attribute='User-Profile' and username = '%{User-Name}' limit 1) order by priority limit 1)}"
to
Rd-Total-Data := "%{sql:Select value from radcheck where attribute='Rd-Total-Data' and username='%{request:User-Name}'}"
reason is Rd-Total-Data is user based which is in radcheck. radgroupcheck return null to me.
Next,
I integrate this concept to topup concept. Which when your quota is finish, coa will a kick you out. next login you will get throttled speed. Then, if you top your quota, you will be kick out again. To refresh your speed.
Due to quota counter reason, when you are in throttled speed. the account in sql is not recorded.
Hi,
Am using a Mikrotik Routerboard RB 3011 as my NAS. When the data is capped, the user connects and when the data allocation gets used up, the user is not being disconnected.
Please assist