Help‎ > ‎Security‎ > ‎

FreeRADIUS Google Dual Factor Authenticator

Introduction


Google Authenticator (http://code.google.com/p/google-authenticator/) is a great free dual factor authentication system.  "The Google Authenticator project includes implementations of one-time passcode generators for several mobile platforms".  It can be used in conjunction with FreeRADIUS to provide Free 2 factor authentication, something that usually costs a ton of money.

This all works because of a library called PAM.  PAM is "Pluggable Authentication Modules" for Linux system user and password authentication.  For more information on PAM see http://www.linux-pam.org/.  Google Authenticator has a PAM module that is included as part of the project.  PAM is the glue that allows FreeRADIUS to talk to Google Authenticator.

FreeRADIUS is a popular open source radius server.  Radius is a standardized authentication system that can be used to authenticate many different devices including VPNs, Routers, Switches, Computers, and much more.  For more information on FreeRADIUS see http://freeradius.org/.

Tutorial


Now, how to set it up.

For the purpose of this tutorial I will be using Ubuntu 12.04 Server, but this should be able to adapt to many different distributions.

Yes, I know there is a package...  Don't install it.  If you do install it, remove it.  We need to compile the source.

So start out with this:

NTP Time Sync Install (Optional, but Highly Recommended)

The default behavior of the Google Authenticator is to use a time based token.  Because of this you will likely want to install NTP so that your server time is always correct.   This is especially important on a virtual machine, due to the increased time drift that is often a problem with Virtual Machine environments.

sudo bash
apt-get update
apt-get install ntp

Install FreeRADIUS and other Necessary Packages


sudo bash
apt-get update
apt-get install build-essential libpam0g-dev freeradius git libqrencode3 

Download Google Authenticator Pam Module Source

cd ~
git clone https://code.google.com/p/google-authenticator/
cd google-authenticator/libpam/
make
make install


Configure Local Unix Groups

We will need to add a group called 'radius-disabled' to drop users in, when you want to disable access (rather than removing them entirely)

addgroup radius-disabled

Configure FreeRADIUS

FreeRADIUS must run as root for this to work.  Yeah, I know it's not good practice, but thats the way this works.  In other words, you may want to limit the use of this box to FreeRADIUS authentication only.  The reason for this is so that FreeRADIUS can access the .google_authenticator token in each home directory.  Otherwise FreeRADIUS does not have access.


First, edit /etc/freeradius/radusd.conf

You need to locate the following lines:

# user/group: The name (or #number) of the user/group to run radiusd as.
#
#   If these are commented out, the server will run as the user/group
#   that started it.  In order to change to a different user/group, you
#   MUST be root ( or have root privleges ) to start the server.
#
#   We STRONGLY recommend that you run the server with as few permissions
#   as possible.  That is, if you're not using shadow passwords, the
#   user and group items below should be set to radius'.
#
#  NOTE that some kernels refuse to setgid(group) when the value of
#  (unsigned)group is above 60000; don't use group nobody on these systems!
#
#  On systems with shadow passwords, you might have to set 'group = shadow'
#  for the server to be able to read the shadow password file.  If you can
#  authenticate users while in debug mode, but not in daemon mode, it may be
#  that the debugging mode server is running as a user that can read the
#  shadow info, and the user listed below can not.
#
#  The server will also try to use "initgroups" to read /etc/groups.
#  It will join all groups where "user" is a member.  This can allow
#  for some finer-grained access controls.
#
user = freerad
group = freerad

and then change the user & group lines to look like the following

user = root
group = root

Once you have done this, save and close the file.

Next edit, /etc/freeradius/users


You need to locate the following lines:

#
# Deny access for a group of users.
#
# Note that there is NO 'Fall-Through' attribute, so the user will not
# be given any additional resources.
#

We will start by creating a group that you can add users to and disable their access.

Directly after these lines add the following code:

DEFAULT         Group == "radius-disabled", Auth-Type := Reject
                Reply-Message = "Your account has been disabled."

Now, we will add the default rule to use the PAM libraries to authenticate users

Directly after the previous lines of code, add the following:

DEFAULT        Auth-Type := PAM

Now edit, /etc/freeradius/sites-enabled/default


Locate the following lines of code:

authenticate {
        #
        #  PAP authentication, when a back-end database listed
        #  in the 'authorize' section supplies a password.  The
        #  password can be clear-text, or encrypted.
        Auth-Type PAP {
                pap
        }

        #
        #  Most people want CHAP authentication
        #  A back-end database listed in the 'authorize' section
        #  MUST supply a CLEAR TEXT password.  Encrypted passwords
        #  won't work.
        Auth-Type CHAP {
chap
        }

        #
        #  MSCHAP authentication.
        Auth-Type MS-CHAP {
                mschap
        }

        #
        #  If you have a Cisco SIP server authenticating against
        #  FreeRADIUS, uncomment the following line, and the 'digest'
        #  line in the 'authorize' section.
        digest

#
        #  Pluggable Authentication Modules.
#       pam

        #
        #  See 'man getpwent' for information on how the 'unix'
        #  module checks the users password.  Note that packets
        #  containing CHAP-Password attributes CANNOT be authenticated
        #  against /etc/passwd!  See the FAQ for details.
        #
        #  For normal "crypt" authentication, the "pap" module should
        #  be used instead of the "unix" module.  The "unix" module should
        #  be used for authentication ONLY for compatibility with legacy
        #  FreeRADIUS configurations.
        #
        unix

        # Uncomment it if you want to use ldap for authentication
        #
        # Note that this means "check plain-text password against
        # the ldap database", which means that EAP won't work,
        # as it does not supply a plain-text password.
#       Auth-Type LDAP {
#               ldap
#       }

        #
        #  Allow EAP authentication.
        eap

        #
        #  The older configurations sent a number of attributes in
        #  Access-Challenge packets, which wasn't strictly correct.
        #  If you want to filter out these attributes, uncomment
        #  the following lines.
        #
#       Auth-Type eap {
#               eap {
#                       handled = 1
#               }
#               if (handled && (Response-Packet-Type == Access-Challenge)) {
#                       attr_filter.access_challenge.post-auth
#                       handled  # override the "updated" code from attr_filter
#               }
#       }
}

Uncomment the line with "pam" so it should look like this:

        #  Pluggable Authentication Modules.
        pam

Configure PAM


PAM must be configured to use the local Unix password in combination with the Google Authenticator password.

Edit /etc/pam.d/radiusd

Currently the file should look like this:

#                                                                                                                                        
# /etc/pam.d/radiusd - PAM configuration for FreeRADIUS                                                                                  
#                                                                                                                                        

# We fall back to the system default in /etc/pam.d/common-*                                                                              
#                                                                                                                                        

@include common-auth
@include common-account
@include common-password
@include common-session


We need to comment out all the lines that start with @ and then add the following code:

auth requisite pam_google_authenticator.so forward_pass
auth required pam_unix.so use_first_pass


So in the end, the file should look like this:

#                                                                                                                            
# /etc/pam.d/radiusd - PAM configuration for FreeRADIUS                                                                      
#                                                                                                                            

# We fall back to the system default in /etc/pam.d/common-*                                                                  
#                                                                                                                            

#@include common-auth                                                                                                        
#@include common-account                                                                                                     
#@include common-password                                                                                                    
#@include common-session                                                                                                     

auth requisite pam_google_authenticator.so forward_pass
auth required pam_unix.so use_first_pass


Setup a local test user

adduser test

choose a easy password to remember, for this example I used "test123"

cd /home/test/
su test
google-authenticator

If everything worked right you should see something that looks like this:

test@FreeDualFactor:~$ google-authenticator 

Do you want authentication tokens to be time-based (y/n) y
https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/test@FreeDualFactor%3Fsecret%3DXQH7L6A7W6OK3JYS
                                                                          
 
                                                                        
Your new secret key is: XQH7L6A7W6OK3JYS
Your verification code is 158428
Your emergency scratch codes are:
  60469537
  95985887
  80580778
  52386153
  52951956

Do you want me to update your "/home/test/.google_authenticator" file (y/n) y

Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n) y

By default, tokens are good for 30 seconds and in order to compensate for
possible time-skew between the client and the server, we allow an extra
token before and after the current time. If you experience problems with poor
time synchronization, you can increase the window from its default
size of 1:30min to about 4min. Do you want to do so (y/n) n

If the computer that you are logging into isn't hardened against brute-force
login attempts, you can enable rate-limiting for the authentication module.
By default, this limits attackers to no more than 3 login attempts every 30s.
Do you want to enable rate-limiting (y/n) y



You can configure yours how you see fit.

Scan once you get your custom QR Code, scan it in to your Google Authenticator App.

The App should generate a rotating code that you can use for your dual factor authentication.

Test your Configuration

service freeradius restart

You will want to use a command called "radtest" to test your configuration.

radtest <username> <unix_password><google_auth> localhost 18120 testing123

testing123 is a default secret for the localhost client, used for testing purposes.  You can find this in /etc/freeradius/clients.conf

so since my password is "test123" and the current google authenticator key is "696720" my test looks like this:

radtest test test123696720 localhost 18120 testing123

If it works right, you should get something like this:

root@FreeDualFactor:~# radtest test test123696720 localhost 18120 testing123
Sending Access-Request of id 154 to 127.0.0.1 port 1812
User-Name = "test"
User-Password = "test123696720"
NAS-IP-Address = 127.0.1.1
NAS-Port = 18120
rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=154, length=20


Debugging


if for some strange reason it doesn't work.  You can stop freeradius and start it up in debugging mode like this:

service freeradius stop
freeradius -XXX



Good luck, and hopefully this works as well for you as it has for me.




Comments