Linux MFA using PAM_Radius and RSA

When you look down the list of Linux distributions officially supported by RSA there are omissions.  Fear not for while they may not be officially supported by the PAM agent it doesn't mean you can't make MFA work.  For this example we used Debian10, PAM_Radius and RSA via radius to effect MFA for SSH access.  The end result was even more pleasing as we managed to get granularity across users and services. it will also work on Ubuntu...

I am assuming you know how to configure the RSA (or your radius authentication server) side of things eg set up a radius client, associated agent and to set up any firewall rules neccesary between the boxes. Also, I assume you have loaded nano on your linux server and probably nc to test communictions. Please excuse the fact that I don't always tell you to nano something, it got a bit tedious to type. You will also be restarting ssh a lot more than indicated to test as you go.

Section 1 Preliminary notes

Always ensure you have a working ssh session to the linux host in question at all times in case you have to roll back changes cause you have locked yourself out, wouldn't hurt to take a backup or snapshot as well

Section 2 The Solution

2.1 Install pam_radius_auth and other libraries:

$ sudo apt-get install libpam-radius-auth libpam0g-dev gcc

2.2 Edit sshd_config

$ sudo nano /etc/ssh/sshd_config

Edit to ensure that ChallengeResponseAuthentication yes is enabled and does not include a hash tag ( # ), as follows:

ChallengeResponseAuthentication yes
#ChallengeResponseAuthentication no

Edit to ensure that UsePAM yes is enabled and does not include a hash tag ( # ), as follows:

#UsePAM no
UsePAM yes

2.3 Edit sshd:

$ sudo nano /etc/pam.d/sshd

At the beginning of the file, add the following line:

auth      sufficient       pam_radius_auth.so

By way of explanation this will invoke a radius lookup on all ssh users, the term sufficient means that it the auth is succesful then the user will be logged in, it it is not successful it will fall back to the next avaliable auth method in sshd which is typically local user password. Later on we will disucss how to strenghten this, however its a good start and stops us locking ourselves out.

2.4 Edit pam_radius_auth.conf:

$ sudo nano /etc/pam_radius_auth.conf

Add as many lines as you have radius servers:

# server[:port]     shared_secret       timeout (s)
IP/FQDN             shared_secret            60

The IP Address / FQDN is that of the radius server

shared_secret is the shared secret configured

60 is the number of seconds for communication between the servers

5 Set the correct file attribures on pam_radius_auth.conf:

$ sudo chmod 600 pam_radius_auth.conf

2.5 Copy the pam_radius_auth.conf to its final location:

$ sudo mkdir /etc/raddb
$ sudo cp /etc/pam_radius_auth.conf /etc/raddb/server

2.6 Restart the SSHD service:

$ sudo service ssh restart

Section 3 Apply Conditional Access

Ok radius auth is now ready to go for all users of ssh. Now how about if we want it to be applied to a group or to be excluded by a group

3.1 Create a user group on the Linux instance. MFA/PAM will be disabled for users present in this new group:

$ sudo groupadd <groupname>

3.2 Create User or add existing user to newly created group:

$ sudo useradd <username>
$ sudo passwd <username>
$ sudo usermod -a -G <groupname> <username>

Note if you wish to remove a user form a group use:

$ sudo deluser <username> <groupname>

33 Edit /etc/pam.d/sshd file and add the below statement to skip the PAM_Radius module for the newly created group:

auth [success=done default=ignore] pam_succeed_if.so user ingroup <groupname>

or try this..

auth [success=1 default=ignore] pam_succeed_if.so user ingroup <groupname>

The success=1 syntax means skip 1 line in the file if the condition returns true. What this means is if we have the following in our sshd config file then a true condition on the first line means we will skip the second thereby missing the radius auth and flowing on to the next auth type in sshd which is typically the local password login. I am sure you the reader can also come up with many variations on this theme to suit themsevles.

auth [success=1 default=ignore] pam_succeed_if.so user ingroup <groupname>
auth      sufficient       pam_radius_auth.so

3.4 Restart the sshd service:

$ sudo service ssh restart

Section 4 Enforce Authentication

So far so good, what if we want to enforce MFA and a local password, Well try this.

4.1 Edit /etc/pam.d/sshd

Change the sufficient systnax to required on the following authentication methods (if they are not alrewady set):

auth      required       /usr/lib/security/pam_radius_auth.so 
session   required     pam_loginuid.so

What this will do is prompt for the password (MFA code) then again prompt for the password (local password). Both are required. How about we adjust the prompt to make it nice:

4.2 Adjust the prompt by editing /etc/pam/d/sshd

Substitute whatever text you require for the word MFA

auth      required       /usr/lib/security/pam_radius_auth.so prompt=MFA

4.3 Restart the sshd service

$ sudo service ssh restart

Section 5 The Result

The end result should look like this

login as:

Keyboard-interactive authentication prompts from server:

| MFA:

| Password:

End of keyboard-interactive prompts from server

Finally you can apply this solution individually to different services by creating or editing a appropriate configuration file associated with the service in /etc/pam.d, you can also apply it to sudo/su users only via the same mechanism.

Posted in SecurID on Feb 17, 2021