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:
>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 ########################################
Links and Hints
To get more information, feel free to take a look at his links:
http://wiki.freeradius.org/Proxy.conf
http://wiki.freeradius.org/Hints
http://freeradius.1045715.n5.nabble.com/Regex-remove-realm-from-username-td2776961.html