RADIUS Proxy

This documentation will show how to setup a RADIUS Server that acts as a proxy for other RADIUS servers. This can be very useful, if you want to point to different RADIUS servers based on the users realms. The RADIUS proxy in this documentation is installed on a Debian 6.0.4 GNU/Linux machine with kernel 2.6.32-5-686.

Initial Position

Let's assume we already have 4 RADIUS servers.

2 Servers to authenticate Hardware Safeword token

#SAFEWORD-RADIUS-SERVERS
192.168.178.25 sfwrd1.mydomain.local
192.168.178.25 sfwrd2.mydomain.local

The Safeword usernames can be a lowercase “v” then 1 or 2 uppercase letters followed by 6 numbers, eg. vA123456 or vBC654321.

2 Servers to authenticate Smartphones running the Google Authenticator App

#GOOGLE-AUTHENTICATOR-RADIUS-SERVERS
172.16.1.27    googl1.mydomain.local
172.16.1.28    googl2.mydomain.local

The Google Authenticator usernames can be a lowercase “g” and a capital “G” followed by anything else.

We also have a VPN-Server that is able to use RADIUS authentication. We want to be able to authenticate at the VPN-Server either with a Safeword Hardware OTP-Token or the Google Authenticator Application on a smartphone. The VPN-Server only allows to define a single RADIUS server for authentication. Usually this can not be done. This is a situation, where a RADIUS Proxy comes in handy.

Installation of FreeRADIUS

To install the FreeRADIUS server on our Debian machine we simply enter the following commands as the root user:

apt-get install freeradius freeradius-utils

This will install FreeRADIUS, the FreeRADIUS client utilities and all necessary dependencies.

Preconfiguration of FreeRADIUS

FreeRADIUS uses a default password “testing123” in it's configuration files. So replace the password in the following line

secret          = testing123

in all of the following configuration files

/etc/freeradius/clients.conf
/etc/freeradius/proxy.conf

with your password. For this documentation I will use the password “WeSetupARadiusProxy” as password, so I change the line in clients.conf and proxy.conf to

secret          = WeSetupARadiusProxy

to make sure we differ from the default.

Realms based on usernames

/etc/freeradius/hints

To be able to differ between users that use a Safword OTP or the Google Authenticator App we have to define a rule for each of them that results in a realm added to the username. This can easily be done in the hints file. To learn how to do this you should take a look at this page http://wiki.freeradius.org/Hints. We need 2 entries in the file

/etc/freeradius/hints

that look this way:

Hint for Google Authenticator usernames

# GOOGLE
#Detect gA at start of username and if so add realm GOOGLE at the end
# see http://wiki.freeradius.org/Hints
DEFAULT User-Name =~ "^(gA.*)"
        User-Name := "%{1}@GOOGLE"

and an equivalent for Safeword OTP usernames

# SAFEWORD
#Detect lowercase "v", 1 or 2 captial letters followed by 6 numbers
#at start of username to identify a SAFEWORD token
#and if so add realm SAFEWORD at the end
#see http://wiki.freeradius.org/Hints
DEFAULT User-Name =~ "^(v[A-Z]{1,2}[0-9]{6})"
        User-Name := "%{1}@SAFEWORD"

This means, if eg. the user vF932221 tries to login, the SAFEWORD rule will apply and add the realm SAFEWORD to the username. So after this process, the username will be:

vF932221@SAFEWORD

Also when eg. a username gA123443 tries to login the GOOGLE rule will apply and add the realm GOOGLE to the username. The result will look like this:

gA123443@GOOGLE

For this documentation I will post the complete file (without comments) here:

DEFAULT       Suffix == ".ppp", Strip-User-Name = Yes
      Hint = "PPP",
      Service-Type = Framed-User,
      Framed-Protocol = PPP
DEFAULT       Suffix == ".slip", Strip-User-Name = Yes
      Hint = "SLIP",
      Service-Type = Framed-User,
      Framed-Protocol = SLIP
DEFAULT       Suffix == ".cslip", Strip-User-Name = Yes
      Hint = "CSLIP",
      Service-Type = Framed-User,
      Framed-Protocol = SLIP,
      Framed-Compression = Van-Jacobson-TCP-IP
      
DEFAULT User-Name =~ "^(gA.*)"
      User-Name := "%{1}@GOOGLE"
DEFAULT User-Name =~ "^(w[A-Z]{1,2}[0-9]{6})"
        User-Name := "%{1}@SAFEWORD"
        

RADIUS Proxy Configuration

/etc/freeradius/proxy.conf

home_server

First of all we have to add all RADIUS servers we want to use as a home_server in the file

/etc/freeradius/proxy.conf

For the 2 RADUS servers that to Safeword OTP authentication we use this entries:

home_server safeword1 {
        type = auth+acct
        ipaddr = 192.168.178.25
        port = 1812
        secret = letmesafeword
        require_message_authenticator = yes
        response_window = 20
        zombie_period = 40
        revive_interval = 120
        status_check = status-server
        check_interval = 30
        num_answers_to_alive = 3
}



home_server safeword2 {
        type = auth+acct
        ipaddr = 192.168.178.26
        port = 1812
        secret = letmesafeword
        require_message_authenticator = yes
        response_window = 20
        zombie_period = 40
        revive_interval = 120
        status_check = status-server
        check_interval = 30
        num_answers_to_alive = 3
}

For the 2 RADIUS Servers doing Google Authenticator we add this entries:

home_server google1 {
        type = auth+acct
        ipaddr = 172.16.1.27
        port = 1812
        secret = letmegoogle
        require_message_authenticator = yes
        response_window = 20
        zombie_period = 40
        revive_interval = 120
        status_check = status-server
        check_interval = 30
        num_answers_to_alive = 3
}

home_server google2 {
        type = auth+acct
        ipaddr = 172.16.1.28
        port = 1812
        secret = letmegoogle
        require_message_authenticator = yes
        response_window = 20
        zombie_period = 40
        revive_interval = 120
        status_check = status-server
        check_interval = 30
        num_answers_to_alive = 3
}

We have now defined all RADIUS servers.

home_server_pool

To group the 2 Safeword RADIUS home_server, we create a pool with name “my_safeword_radius_servers” by adding the following entry to /etc/freeradius/proxy.conf

home_server_pool my_safeword_radius_servers {
        type = fail-over
        home_server = safeword1
        home_server = safeword2
}

and of course, we do the same for the home_server that do Google Authenticator via RADIUS but now with the name “my_googleotp_radius_servers”

home_server_pool my_googleotp_radius_servers {
        type = fail-over
        home_server = google1
        home_server = google2        
}

We now have 2 additional home_server_pool's.

realm

We already defined the realms in /etc/freeradius/hints as documented here. Now we have to add this realms to the file /etc/freeradius/proxy.conf so that we can proxy RADIUS requests to home_server_pool s based on their realm.

The realm SAFEWORD looks like this:

realm "SAFEWORD" {
        auth_pool = my_safeword_radius_servers
        acct_pool = my_safeword_radius_servers
}

pointing to the home_server_pool “my_safeword_radius_servers”

For the realm GOOGLE we use this entry:

realm "GOOGLE" {
        auth_pool = my_googleotp_radius_servers
        acct_pool = my_googleotp_radius_servers
}

If a realm is handled by the RADIUS proxy itself (locally), make sure you just use the following entry:

realm "GOOGLE" {
   #     do nothing
   #     this means use the local server
}

Testing our FreeRADIUS

Prerequisites

Allow our server as client on the proxied servers

Before you start testing make sure, that our RADIUS server is allowed as a client on the 4 other RADIUS servers.

Start FreeRADIUS

For a test you should stop the FreeRADIUS service

service freeradius stop

and start FreeRADIUS from the command line to see some debug output.

freeradius -X

If FreeRADIUS stops at this point with an error message, you have to fix this error first, before you continue.

If everything went fine, you should see FreeRADIUS running and waint for requests:

...
... a lot of lines before ...
...
Listening on authentication address * port 1812
Listening on accounting address * port 1813
Listening on authentication address 127.0.0.1 port 18120 as server inner-tunnel
Listening on proxy address * port 1814
Ready to process requests.

Test FreeRADIUS proxy

Now switch to a different terminal on our new FreeRADIUS proxy server and try to authenticate with the radtest utility. Use it with the following syntax:

radtest <username> <password> 127.0.0.1 18120 <radius client password>

Based on our configuration this could look like this:

GOOGLE AUTHENTICATOR

radtest gA123443 592455 127.0.0.1 18120 letmegoogle

or

SAFEWORD TOKEN

radtest vF932221 1212592455 127.0.0.1 18120 letmesafeword

The result for both request should look similar to this:

GOOGLE

>radtest gA123443 592455 127.0.0.1 18120 letmegoogle
Sending Access-Request of id 120 to 127.0.0.1 port 1812
        User-Name = "gA123443"
        User-Password = "592455"
        NAS-IP-Address = 127.0.1.1
        NAS-Port = 18120
rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=120, length=20

SAFEWORD

>radtest vF932221 1212592455 127.0.0.1 18120 letmesafeword
Sending Access-Request of id 120 to 127.0.0.1 port 1812
        User-Name = "vF932221"
        User-Password = "1212592455"
        NAS-IP-Address = 127.0.1.1
        NAS-Port = 18120
rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=120, length=20

The terminal running our FreeRADIUS should show something like this during the authentication:

+- entering group authorize {...}
[preprocess]    expand: %{User-Name} -> gA123443
[preprocess]   hints: Matched DEFAULT at 81
[preprocess]    expand: %{1}@GOOGLE -> gA123443@GOOGLE
++[preprocess] returns ok
...
...
...
[suffix] Looking up realm "GOOGLE" for User-Name = "gA123443@GOOGLE"
[suffix] Found realm "GOOGLE"
[suffix] Adding Stripped-User-Name = "gA123443"
[suffix] Adding Realm = "GOOGLE"
[suffix] Proxying request from user gA123443 to realm GOOGLE
[suffix] Preparing to proxy authentication request to realm "GOOGLE"
++[suffix] returns updated
...
...
...
Sending Access-Request of id 231 to 172.16.1.27 port 1812
...
...
Proxying request 0 to home server 172.16.1.27 port 1812
Sending Access-Request of id 231 to 172.16.1.27 port 1812
        User-Name := "gA123443"
        User-Password = "592455"
...
Going to the next request
Waking up in 0.9 seconds.
rad_recv: Access-Accept packet from host 172.16.1.27 port 1812, id=231, length=25
        Proxy-State = 0x313230
...
...
Found Auth-Type = Accept
Auth-Type = Accept, accepting the user
...
Sending Access-Accept of id 120 to 127.0.0.1 port 55271
Finished request 0.
...
Ready to process requests.

If all tests were okay, stop FreeRADIUS in the terminal with Ctrl+C and start it as a service

service freeradius start

Configuration files

Here are the settings in the configuration files with comments and grouped together

hints

# hints
DEFAULT       Suffix == ".ppp", Strip-User-Name = Yes
      Hint = "PPP",
      Service-Type = Framed-User,
      Framed-Protocol = PPP

DEFAULT       Suffix == ".slip", Strip-User-Name = Yes
      Hint = "SLIP",
      Service-Type = Framed-User,
      Framed-Protocol = SLIP

DEFAULT       Suffix == ".cslip", Strip-User-Name = Yes
      Hint = "CSLIP",
      Service-Type = Framed-User,
      Framed-Protocol = SLIP,
      Framed-Compression = Van-Jacobson-TCP-IP

# GOOGLE
#Detect gA at start of username and if so add realm GOOGLE at the end
# see http://wiki.freeradius.org/Hints
DEFAULT User-Name =~ "^(gA.*)"
      User-Name := "%{1}@GOOGLE"

# SAFEWORD
#Detect lowercase "v", 1 or 2 captial letters followed by 6 numbers
#at start of username to identify a SAFEWORD token
#and if so add realm SAFEWORD at the end
#see http://wiki.freeradius.org/Hints
DEFAULT User-Name =~ "^(v[A-Z]{1,2}[0-9]{6})"
        User-Name := "%{1}@SAFEWORD"

proxy.conf

proxy server {
      default_fallback = no
}
home_server localhost {
      type = auth
      ipaddr = 127.0.0.1
      port = 1812
      secret = letmegoogle
      require_message_authenticator = yes
      response_window = 20
      zombie_period = 40
      revive_interval = 120
      status_check = status-server
      check_interval = 30
      num_answers_to_alive = 3
      coa {
              irt = 2
              mrt = 16
              mrc = 5
              mrd = 30
      }
}
home_server_pool my_auth_failover {
      type = fail-over
      home_server = localhost
}
realm example.com {
      auth_pool = my_auth_failover
}
realm LOCAL {
}
# # # #
# GOOGLE START   #######################################
realm "GOOGLE" {
      auth_pool = my_googleotp_radius_servers
      acct_pool = my_googleotp_radius_servers
}

home_server_pool my_googleotp_radius_servers {
      type = fail-over
      home_server = google1
#     home_server = google2
#     home_server = google3
}

home_server google1 {
        type = auth+acct
        ipaddr = 10.110.111.110
        port = 1812
        secret = letmegoogle
        require_message_authenticator = yes
        response_window = 20
        zombie_period = 40
        revive_interval = 120
        status_check = status-server
        check_interval = 30
        num_answers_to_alive = 3
}
# GOOGLE STOP    #######################################

# SAFEWORD START #######################################
realm "SAFEWORD" {
      auth_pool = my_safeword_radius_servers
      acct_pool = my_safeword_radius_servers
}

home_server_pool my_safeword_radius_servers {
      type = fail-over
      home_server = safeword1
      home_server = safeword2
}

home_server safeword1 {
        type = auth+acct
        ipaddr = 10.120.102.25
        port = 1812
        secret = strongsecrethere
        require_message_authenticator = yes
        response_window = 20
        zombie_period = 40
        revive_interval = 120
        status_check = status-server
        check_interval = 30
        num_answers_to_alive = 3
}

home_server safeword2 {
        type = auth+acct
        ipaddr = 10.120.102.26
        port = 1812
        secret = strongsecrethere
        require_message_authenticator = yes
        response_window = 20
        zombie_period = 40
        revive_interval = 120
        status_check = status-server
        check_interval = 30
        num_answers_to_alive = 3
}
# SAFEWORD STOP ########################################
public/linux/freeradius_proxy.txt · Last modified: 2017/12/19 08:51 by pcfreak
CC Attribution-Share Alike 3.0 Unported
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0