I maintain my systems mostly via SSH and although SSH is secure enough with it’s encryption I want to secure it a bit more. I do use keys a lot and is the proper way to log in via SSH as passwords are not needed anymore. But since I work remotely sometimes and not having my workstation with me, I have to keep allowing password based logins for SSH but don’t want to rely on the password itself, so I started the implementation of 2 factor authentication for SSH using the Google Authenticator. This post will describe the steps necessary to enable 2FA using the Google Authenticator app for the SSH service.
Notes on the Google Authenticator:
As Google has a reputation to scrape literally every piece of information about you and your behaviour online, the authenticator does not send any data to Google (as they say themselves). The numbers generated by the app are processed on your phone itself instead of coming from a server of Google and the data exchanged is only performed between your computer and the server you are connecting to.
Installing the Google Authenticator software on the server:
In order to enable 2FA we need to install the Google Authenticator software on the server as well because we will be using PAM for the authentication process and the software delivers the appropriate module for use with PAM.
To install it op Debian based systems, do:
apt-get install libpam-google-authenticator
On Arch based systems you need to run:
yaourt -Sy google-authenticator-libpam-git
For Arch you need the AUR repo, therefore have yaourt installed on your system!
For Redhat/CentOS based systems:
There is a rpm for the authenticator module, but it seriously outdated, so we need to compile it ourself. First install the required depencies:
sudo yum install make gcc pam-devel
Download and unzip the sourcecode:
wget -O google-authenticator.zip https://github.com/google/google-authenticator/archive/master.zip
Now enter the directory and start the build:
sudo make install
Installing the Google Authenticator app:
Open the app store on your phone and search for the Google Authenticator app and install it.
Configuring the Authenticator on the server:
Login on your server with the user you want to enable the Google Authenticator for and run the following command:
You’ll have to answer the question if you want tokens to be time-based, for extra security I strongly advise you to set it to yes as this will set a expiry time on the token itself.
After this process a URL and a huge QR code will be spewed out on the terminal. The URL shows the same QR code, but in your browser which may be more convenient.
A set of keys and emergency codes are provided, save them in a safe place! You will need these emergency codes in case you lose access to the Google Authenticator app.
3 additional questions will be asked like below:
Your new secret key is: 2IKBRFIFF5FRB7JB
Your verification code is 245699
Your emergency scratch codes are:
Do you want me to update your "/home/jeffrey/.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) y
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
The questions are simple and straightforward and don’t need any extra explanation, for the best security with the tokens you will want to answer yes on all questions except the 3rd question. Note that it says that it will increase the lifetime of a token from 90 seconds to 240 seconds. If you want the best security out of this system you should answer no here but relies heavily on the current system time and your device generating the token, they may not differ more than 90 seconds. If you use NTP on your server the 90 seconds should not be an issue but if it is you should answer yes here.
Setting up the app:
Open the Google Authenticator app on your device and you have the choice to enable via QR code or enter the tokens manually. For this example I will use the manual process, but for faster configuration the QR code is best.
After the name and key is inserted, add the account. After adding the account the app starts generating tokens:
Configuring PAM and SSH:
In order to activate the Google Authenticator module using PAM we need to open the PAM config for SSH:
sudo nano /etc/pam.d/sshd
Add the following line to the top of the file and save it:
auth required pam_google_authenticator.so
Open the SSH config:
sudo nano /etc/ssh/sshd_config
Search for the keyword
If it's commented out like:
# ChallengeResponseAuthentication no
You need to change it to:
If the line does not exist within the configuration file, just add it (which is the same as above) and save your changes:
Now restart SSH to activate the settings changed:
For Debian based systems:
sudo service ssh restart
For Arch based systems:
sudo systemctl restart sshd.service
For Redhat/CentOS based systems:
sudo service sshd restart
Logging in via SSH with the authenticator:
Now that the settings are active we want to test it. I've done it on my local machine, so in this example I'll connect to localhost:
[jeffrey@jeffrey ~]$ ssh localhost
As you can see it's working!
Note on SSH-keys:
If you already use SSH-keys to login without password on your server this will bypass the Google Authenticator. Looking at the way keys work and how they need to be deployed you basically have performed a 2FA when logging in to the server and placing your pubkey there. If you work from your private desktop this will work just fine but in my opinion for mobile devices that can be used on-the-go it's not.
For mobile devices that may get stealed or might get lost it's absolutely a pre to sign your SSH-key with a password. this way you will have to enter a password every time to login to the server, but that's only for decrypting the key and then will login with that key.
You can create a key with password via the following line:
ssh-keygen -t rsa -N 'YOUR_PASSWORD'
This will overwrite your current keyfile! Once generated place the publickey on the server and you're done. This will function as 2FA as well and will bypass the Google Authenticator module.