Is it possible to automate a Disconnect-Request based on exceeded Monthly-Usage?

classic Classic list List threaded Threaded
9 messages Options
| Threaded
Open this post in threaded view
|

Is it possible to automate a Disconnect-Request based on exceeded Monthly-Usage?

Houman
Hello,

I have setup the FreeRadius like the following to prevent a user
from logging in after his monthly usage has been exceeded.

echo 'ATTRIBUTE       Monthly-Usage          3001    integer64' >>
/etc/freeradius/3.0/dictionary

sed -i '/authorize {/a\
   update request {\
                Monthly-Usage = "%{sql:SELECT
COALESCE((SUM(`acctoutputoctets`)), 0) FROM radacct WHERE
`username`='"'"'%{User-Name}'"'"' AND
Month(acctupdatetime)=(Month(NOW())) AND
Year(acctupdatetime)=Year(NOW())}"\
        }\
' /etc/freeradius/3.0/sites-enabled/default

INSERT INTO radcheck (username,attribute,op,VALUE) VALUES
('houman','Monthly-Usage','<',10000);

While this works fine, the user won't be disconnected after the
monthly-usage has been exceeded. Instead only if the user disconnects
voluntarily and tries to reconnect again would he be prevented.

So I'm trying to find a way to disconnect the user the moment his limit has
been reached.

After some research I have come across Dynamic Authorization extension and
have enabled it like this:

*dae {*

*  enable = yes     *

*  listen = 0.0.0.0  *

*  port = 3799       *

*  secret = secret123     *

*}*


Now I can disconnect myself from the command line, like this:


*echo User-Name=houman | radclient -x 127.0.0.1:3799
<http://127.0.0.1:3799> disconnect ''secret123''*


That's very nice. So I could run a Python script via a crontab job to check
every minute to see which users have exceeded their monthly-usage and
disconnect them.

But I was wondering if there is a way to automate the disconnect directly
via free radius so that I don't have to run the crontab job.

Is there a way that I'm overlooking?

Many Thanks,
Houman
-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

Re: Is it possible to automate a Disconnect-Request based on exceeded Monthly-Usage?

Jorge Pereira-2
Houman,

        First of all, verify if your NAS has support to CoA. If yes, enable it. Then, you should configure the home_server { … } following the sample in proxy.conf, therefore you will be able to interact with your NAS sending the commands like Disconnect-Request
--
Jorge Pereira
[hidden email]



> On 10 Sep 2019, at 17:06, Houman <[hidden email]> wrote:
>
> Hello,
>
> I have setup the FreeRadius like the following to prevent a user
> from logging in after his monthly usage has been exceeded.
>
> echo 'ATTRIBUTE       Monthly-Usage          3001    integer64' >>
> /etc/freeradius/3.0/dictionary
>
> sed -i '/authorize {/a\
>   update request {\
>                Monthly-Usage = "%{sql:SELECT
> COALESCE((SUM(`acctoutputoctets`)), 0) FROM radacct WHERE
> `username`='"'"'%{User-Name}'"'"' AND
> Month(acctupdatetime)=(Month(NOW())) AND
> Year(acctupdatetime)=Year(NOW())}"\
>        }\
> ' /etc/freeradius/3.0/sites-enabled/default
>
> INSERT INTO radcheck (username,attribute,op,VALUE) VALUES
> ('houman','Monthly-Usage','<',10000);
>
> While this works fine, the user won't be disconnected after the
> monthly-usage has been exceeded. Instead only if the user disconnects
> voluntarily and tries to reconnect again would he be prevented.
>
> So I'm trying to find a way to disconnect the user the moment his limit has
> been reached.
>
> After some research I have come across Dynamic Authorization extension and
> have enabled it like this:
>
> *dae {*
>
> *  enable = yes     *
>
> *  listen = 0.0.0.0  *
>
> *  port = 3799       *
>
> *  secret = secret123     *
>
> *}*
>
>
> Now I can disconnect myself from the command line, like this:
>
>
> *echo User-Name=houman | radclient -x 127.0.0.1:3799
> <http://127.0.0.1:3799> disconnect ''secret123''*
>
>
> That's very nice. So I could run a Python script via a crontab job to check
> every minute to see which users have exceeded their monthly-usage and
> disconnect them.
>
> But I was wondering if there is a way to automate the disconnect directly
> via free radius so that I don't have to run the crontab job.
>
> Is there a way that I'm overlooking?
>
> Many Thanks,
> Houman
> -
> List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html

-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

Re: Is it possible to automate a Disconnect-Request based on exceeded Monthly-Usage?

Alan DeKok-2
In reply to this post by Houman
On Sep 10, 2019, at 4:06 PM, Houman <[hidden email]> wrote:
> I have setup the FreeRadius like the following to prevent a user
> from logging in after his monthly usage has been exceeded.

  That's good.

> While this works fine, the user won't be disconnected after the
> monthly-usage has been exceeded. Instead only if the user disconnects
> voluntarily and tries to reconnect again would he be prevented.

  See sites-available/originate-coa

> So I'm trying to find a way to disconnect the user the moment his limit has
> been reached.

  That's what "originate-com" is for.

  The documentation isn't perfect, but it should be good.  When you receive an accounting request packet, check for over the limit, and if so, send a Disconnect-Request packet.

  You'll need to set up a home server, etc.

> After some research I have come across Dynamic Authorization extension and
> have enabled it like this:

  That's for *receiving* CoA packets.  You want the server to *send* CoA packets.

> Now I can disconnect myself from the command line, like this:
>
> *echo User-Name=houman | radclient -x 127.0.0.1:3799
> <http://127.0.0.1:3799> disconnect ''secret123''*

  Well, no.  You're sending FreeRADIUS a Disconnect-Request packet.  That doesn't send the packet to the NAS.  FreeRADIUS just goes "yup, I got a packet'.

  You still need to send the packet to the NAS.

  Alan DeKok.


-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

Re: Is it possible to automate a Disconnect-Request based on exceeded Monthly-Usage?

Houman
In reply to this post by Houman
Hi Alan and Jorge,

Sorry, I should have explained that I'm using StrongSwan as my NAS, which
is supporting CoA :

---

StrongSwan Release 4.6.3
<https://wiki.strongswan.org/projects/strongswan/wiki/463> introduces
support for the RADIUS Session-Timeout attribute and the Dynamic
Authorization extension, RFC 5176.

A received Session-Timeout from the RADIUS backend is enforced using
Repeated Authentication, RFC 4478.

The Dynamic Authorization Extension allows a RADIUS backend to actively
terminate a session using a Disconnect-Request, or change the timeout of a
session using a Session-Timeout attribute in a CoA-Request. The extension
is enabled using a *dae* section in the *eap-radius* configuration
---

I can see when I send a Disconnect-Request manually like this:

echo User-Name=houman | radclient -x 127.0.0.1:3799 disconnect ''secret123''

The NAS is able to see the CoA packet and disconnects the user already.

I have found the home server example in sites-available/originate-coa. I
think I have to set it up under /etc/freeradius/3.0/proxy.cnf.

Alan, I'm a bit lost here when you said:

> That's what "originate-com" is for.
> The documentation isn't perfect, but it should be good.  When you receive
an accounting >request packet, check for over the limit, and if so, send a
Disconnect-Request packet.

I think you mean I have to do that
in /etc/freeradius/3.0/sites-enabled/default under the section:

update request { ... }

In what programming language do I have to do that? I think it has to be in
SQL right?

I already do this to capture the monthly usage upon each request:

update request {

                Monthly-Usage = "%{sql:SELECT
COALESCE((SUM(`acctoutputoctets`)), 0) FROM radacct WHERE
`username`='%{User-Name}' AND Month(acctupdatetime)=(Month(NOW())) AND
Year(acctupdatetime)=Year(NOW())}"

        }

Now I need to add another line underneath to compare the Monthly-Usage
against a value and then send the Disconnect-Request if it's greater than
the value.  How Do I raise the Disconnect-Request?


Many Thanks,

Houman
-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

Re: Is it possible to automate a Disconnect-Request based on exceeded Monthly-Usage?

Alan DeKok-2
On Sep 11, 2019, at 3:05 AM, Houman <[hidden email]> wrote:
>
> Sorry, I should have explained that I'm using StrongSwan as my NAS, which
> is supporting CoA :

  That's nice, but sort of assumed.  If the NAS doesn't support CoA, then there's no point in sending it CoA packets.

> I have found the home server example in sites-available/originate-coa. I
> think I have to set it up under /etc/freeradius/3.0/proxy.cnf.

  I'm not sure what that means.  Set "it" up?  Set *what* up?

  If you read the "originate-coa" virtual server, you will see what you have to set up.  So did you do that?

> Alan, I'm a bit lost here when you said:
>
>> That's what "originate-com" is for.
>> The documentation isn't perfect, but it should be good.  When you receive
> an accounting >request packet, check for over the limit, and if so, send a
> Disconnect-Request packet.
>
> I think you mean I have to do that
> in /etc/freeradius/3.0/sites-enabled/default under the section:
>
> update request { ... }

  In the "preacct" or "accounting" sections.

> In what programming language do I have to do that? I think it has to be in
> SQL right?

  If your users are in SQL, you check their usage via SQL queries.

> I already do this to capture the monthly usage upon each request:
>
> update request {
>
>                Monthly-Usage = "%{sql:SELECT
> COALESCE((SUM(`acctoutputoctets`)), 0) FROM radacct WHERE
> `username`='%{User-Name}' AND Month(acctupdatetime)=(Month(NOW())) AND
> Year(acctupdatetime)=Year(NOW())}"
>
>        }

  OK.

> Now I need to add another line underneath to compare the Monthly-Usage
> against a value and then send the Disconnect-Request if it's greater than
> the value.  How Do I raise the Disconnect-Request?

  The "originate-coa" virtual server explains that in detail.  Read the comments at the top of that file.  See also "man unlang".

  There *is* extensive documentation on this, that I already pointed you to.  If you have questions about the documentation, ask.  But asking a question *answered in the documentation*, then it looks like you haven't read it.

  Alan DeKok.


-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

Re: Is it possible to automate a Disconnect-Request based on exceeded Monthly-Usage?

Houman
Hi Alan,

Alright, let's go through the steps.

1) Based on sites-available/originate-coa I have inserted the following
into /etc/freeradius/3.0/sites-enabled/default

I have added the home_server after the server default like this:

server default {
   ...
}
home_server example-coa {
        type = coa
        ipaddr = 127.0.0.1
        port = 3799
        secret = secret123
        coa {
                irt = 2
                mrt = 16
                mrc = 5
                mrd = 30
        }
}

Looking at "man unlang", In the server default I have added this section to
the preacct:

preacct {
        preprocess
        if (Monthly-Usage > 300000000000) {
                update coa {
                        &User-Name = "%{User-Name}"
                        &Acct-Session-Id = "%{Acct-Session-Id}"
                        &NAS-IP-Address = "%{NAS-IP-Address}"
                }
        }

This should now send the Disconnect-Request, based on the usage greater
than 300 GB.

Does this make sense what I have done so far?

Thanks,
Houman






On Wed, 11 Sep 2019 at 12:15, Alan DeKok <[hidden email]> wrote:

> On Sep 11, 2019, at 3:05 AM, Houman <[hidden email]> wrote:
> >
> > Sorry, I should have explained that I'm using StrongSwan as my NAS, which
> > is supporting CoA :
>
>   That's nice, but sort of assumed.  If the NAS doesn't support CoA, then
> there's no point in sending it CoA packets.
>
> > I have found the home server example in sites-available/originate-coa. I
> > think I have to set it up under /etc/freeradius/3.0/proxy.cnf.
>
>   I'm not sure what that means.  Set "it" up?  Set *what* up?
>
>   If you read the "originate-coa" virtual server, you will see what you
> have to set up.  So did you do that?
>
> > Alan, I'm a bit lost here when you said:
> >
> >> That's what "originate-com" is for.
> >> The documentation isn't perfect, but it should be good.  When you
> receive
> > an accounting >request packet, check for over the limit, and if so, send
> a
> > Disconnect-Request packet.
> >
> > I think you mean I have to do that
> > in /etc/freeradius/3.0/sites-enabled/default under the section:
> >
> > update request { ... }
>
>   In the "preacct" or "accounting" sections.
>
> > In what programming language do I have to do that? I think it has to be
> in
> > SQL right?
>
>   If your users are in SQL, you check their usage via SQL queries.
>
> > I already do this to capture the monthly usage upon each request:
> >
> > update request {
> >
> >                Monthly-Usage = "%{sql:SELECT
> > COALESCE((SUM(`acctoutputoctets`)), 0) FROM radacct WHERE
> > `username`='%{User-Name}' AND Month(acctupdatetime)=(Month(NOW())) AND
> > Year(acctupdatetime)=Year(NOW())}"
> >
> >        }
>
>   OK.
>
> > Now I need to add another line underneath to compare the Monthly-Usage
> > against a value and then send the Disconnect-Request if it's greater than
> > the value.  How Do I raise the Disconnect-Request?
>
>   The "originate-coa" virtual server explains that in detail.  Read the
> comments at the top of that file.  See also "man unlang".
>
>   There *is* extensive documentation on this, that I already pointed you
> to.  If you have questions about the documentation, ask.  But asking a
> question *answered in the documentation*, then it looks like you haven't
> read it.
>
>   Alan DeKok.
>
>
> -
> List info/subscribe/unsubscribe? See
> http://www.freeradius.org/list/users.html
-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

Re: Is it possible to automate a Disconnect-Request based on exceeded Monthly-Usage?

Alan DeKok-2
On Sep 11, 2019, at 2:15 PM, Houman <[hidden email]> wrote:
>
> Alright, let's go through the steps.
>
> 1) Based on sites-available/originate-coa I have inserted the following
> into /etc/freeradius/3.0/sites-enabled/default
>
> I have added the home_server after the server default like this:

  That works... but it's generally recommended to put home servers into proxy.conf.  That way you can find them later, as they're all in a consistent place.

> server default {
>   ...
> }
> home_server example-coa {
>        type = coa
>        ipaddr = 127.0.0.1

  Uh...  is your NAS on localhost?  Or is your NAS elsewhere in the network?

  You probably *don't* want to send CoA packets to FreeRADIUS.  As I explained before, this will NOT kick the user offline.

> Looking at "man unlang", In the server default I have added this section to
> the preacct:
>
> preacct {
>        preprocess
>        if (Monthly-Usage > 300000000000) {
>                update coa {
>                        &User-Name = "%{User-Name}"
>                        &Acct-Session-Id = "%{Acct-Session-Id}"
>                        &NAS-IP-Address = "%{NAS-IP-Address}"
>                }
>        }

  That's good.

> This should now send the Disconnect-Request, based on the usage greater
> than 300 GB.

  No, it will send a "coa" packet.  Because you've used the word "coa".  If you want a disconnect, use "disconnect", as is documented in the originate-coa file I said to read, AND in "man unlang" I said to read.

> Does this make sense what I have done so far?

   Mostly.  See the comments above.

  And read the NAS documentation to see which attributes are needed in a Disconnect-Request packet.  We don't know which ones are relevant.  If you get the list wrong, then then the NAS will send a Disconnect-NAK response.  And won't tell you which attributes it was looking for.

  Alan DeKok.


-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

Re: Is it possible to automate a Disconnect-Request based on exceeded Monthly-Usage?

Houman
Hi Alan,

Great news, It almost works now.

The issue I get is now the conditional here:

preacct {
        preprocess
        if (Monthly-Usage > 300000000000) {
            update disconnect {
                        &User-Name = "%{User-Name}"
            }
        }

(5)   NAS-Identifier = "strongSwan"
(5) # Executing section preacct from file
/etc/freeradius/3.0/sites-enabled/default
(5)   preacct {
(5)     [preprocess] = ok
(5)     if (Monthly-Usage > 300000000000) {
(5)     ERROR: Failed retrieving values required to evaluate condition
(5)     policy acct_unique {

If I comment out the conditional there, it disconnects the user after 300
seconds when the next preacct is due.  So fairly happy that this part works.

preacct {
        preprocess
        #if (Monthly-Usage > 300000000000) {
        update disconnect {
                        &User-Name = "%{User-Name}"
        }
        #}

Now I wonder why the attribute is not seen?

I have set it like this:

echo 'ATTRIBUTE Monthly-Usage 3001 integer64' >>
/etc/freeradius/3.0/dictionary

update request {
           Monthly-Usage = "%{sql:SELECT
COALESCE((SUM(`acctoutputoctets`)), 0) FROM radacct WHERE
`username`='"'"'%{User-Name}'"'"' AND Month(acctupdatetime)=(Month(NOW()))
AND Year(acctupdatetime)=Year(NOW())}"
}

When updating the request, the Monthly-Usage attribute should be already
set, so how comes it doesn't recognise the variable within preacct?

Many Thanks,
Houman


On Wed, 11 Sep 2019 at 22:40, Alan DeKok <[hidden email]> wrote:

> On Sep 11, 2019, at 2:15 PM, Houman <[hidden email]> wrote:
> >
> > Alright, let's go through the steps.
> >
> > 1) Based on sites-available/originate-coa I have inserted the following
> > into /etc/freeradius/3.0/sites-enabled/default
> >
> > I have added the home_server after the server default like this:
>
>   That works... but it's generally recommended to put home servers into
> proxy.conf.  That way you can find them later, as they're all in a
> consistent place.
>
> > server default {
> >   ...
> > }
> > home_server example-coa {
> >        type = coa
> >        ipaddr = 127.0.0.1
>
>   Uh...  is your NAS on localhost?  Or is your NAS elsewhere in the
> network?
>
>   You probably *don't* want to send CoA packets to FreeRADIUS.  As I
> explained before, this will NOT kick the user offline.
>
> > Looking at "man unlang", In the server default I have added this section
> to
> > the preacct:
> >
> > preacct {
> >        preprocess
> >        if (Monthly-Usage > 300000000000) {
> >                update coa {
> >                        &User-Name = "%{User-Name}"
> >                        &Acct-Session-Id = "%{Acct-Session-Id}"
> >                        &NAS-IP-Address = "%{NAS-IP-Address}"
> >                }
> >        }
>
>   That's good.
>
> > This should now send the Disconnect-Request, based on the usage greater
> > than 300 GB.
>
>   No, it will send a "coa" packet.  Because you've used the word "coa".
> If you want a disconnect, use "disconnect", as is documented in the
> originate-coa file I said to read, AND in "man unlang" I said to read.
>
> > Does this make sense what I have done so far?
>
>    Mostly.  See the comments above.
>
>   And read the NAS documentation to see which attributes are needed in a
> Disconnect-Request packet.  We don't know which ones are relevant.  If you
> get the list wrong, then then the NAS will send a Disconnect-NAK response.
> And won't tell you which attributes it was looking for.
>
>   Alan DeKok.
>
>
> -
> List info/subscribe/unsubscribe? See
> http://www.freeradius.org/list/users.html
-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

Re: Is it possible to automate a Disconnect-Request based on exceeded Monthly-Usage?

Alan DeKok-2


> On Sep 12, 2019, at 3:09 PM, Houman <[hidden email]> wrote:
>
> Hi Alan,
>
> Great news, It almost works now.
>
> The issue I get is now the conditional here:
>
> preacct {
>        preprocess
>        if (Monthly-Usage > 300000000000) {

  And where does "Monthly-Usage" come from?

  Not from the Accounting-Request packet.

> (5)   preacct {
> (5)     [preprocess] = ok
> (5)     if (Monthly-Usage > 300000000000) {
> (5)     ERROR: Failed retrieving values required to evaluate condition

  Yup.

> Now I wonder why the attribute is not seen?

  Because it doesn't exist.

> I have set it like this:
>
> echo 'ATTRIBUTE Monthly-Usage 3001 integer64' >>
> /etc/freeradius/3.0/dictionary
>
> update request {
>           Monthly-Usage = "%{sql:SELECT
> COALESCE((SUM(`acctoutputoctets`)), 0) FROM radacct WHERE
> `username`='"'"'%{User-Name}'"'"' AND Month(acctupdatetime)=(Month(NOW()))
> AND Year(acctupdatetime)=Year(NOW())}"
> }

  And where is that set?

> When updating the request, the Monthly-Usage attribute should be already
> set, so how comes it doesn't recognise the variable within preacct?

  If it WAS already set, then the debug output would show it being set.

  Odds are that your'e setting it when the Access-Request is received.  The server does *not* magically track attributes across multiple packets.  That's what a database is for.

  Or, you're setting it in the "accounting' section, which (according to the debug output) runs AFTER the "preacct" section.

  If you want to set Monthly-Usage, the you need to *actually set it* ::

preacct {
       preprocess

     update request {
          Monthly-Usage = "%{sql:SELECT
COALESCE((SUM(`acctoutputoctets`)), 0) FROM radacct WHERE
`username`='"'"'%{User-Name}'"'"' AND Month(acctupdatetime)=(Month(NOW()))
AND Year(acctupdatetime)=Year(NOW())}"
    }

       if (Monthly-Usage > 300000000000) {
           update disconnect {
                       &User-Name = "%{User-Name}"
           }
...

  Then it will work.

  Alan DeKok.


-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html