How to set up two-factor authentication for SSH login on Linux

With many high-profile password leaks nowadays, there is a lot of buzz in the industry on "multi-factor" authentication. In a multi-factor authentication system, users are required to go through two distinct authentication procedures: providing something they know (e.g., username/password), and leveraging something they have "physical" access to (e.g., one-time passcode generated by their mobile phone). This scheme is also commonly known as two-factor authentication or two-step verification.

To encourage the wide adoption of two-factor authentication, Google released Google Authenticator, an open-source application that can generate one-time passcode based on open standards (e.g., HMAP/time-based). It is available on multiple platforms including Linux, Android, iOS. Google also offers a pluggable authentication module (PAM) for Google Authenticator, allowing it to be integrated with other PAM-enabled applications such as OpenSSH.

In this tutorial, I will describe how to set up two-factor authentication for an SSH server by integrating Google Authenticator with OpenSSH. I am going to use a Android device to generate one-time passcode. In this tutorial, you will need two things: (1) a Linux host where OpenSSH server is running, and (2) an Android device.

Install Google Authenticator on Linux

The first step is to install Google Authenticator on the Linux host where OpenSSH server is running. Follow this guide to install Google Authenticator and its PAM module on your system.

Once Google Authenticator is ready, you need to go through one-time configuration which involves creating an authentication key from this Linux host, and registering it with an Android device. This will be explained next.

Generate an Authentication Key

To start, simply run Google Authenticator on the Linux server host.

$ google-authenticator

You will see a QR code, as well as a secret key underneath it. The displayed QR code simply represents the numeric secret key. You will need either information to finalize configuration with an Android device.

Google Authenticator will ask you several questions. If you are not sure, you an answer "Yes" to all questions. The emergency scratch codes can be used to regain access to the SSH server in case you lose your Android device, and so cannot generate one-time passcode. So it's better to write them down somewhere.

Run Google Authenticator on Android

As we are going to use an Android device for two-factor authentication, you will need to install Google Authenticator app on Android. Go to Google Play to install it on Android.

When you start Google Authenticator on Android, you will see the following configuration menu.

You can choose either "Scan a barcode" or "Enter provided key" option. The first option allows you to enter the security key, simply by scanning the generated QR code. In this case, you will need to install Barcode Scanner app first. If you choose the second option, you can type the security key using Android keyboard as follows.

Once you register a secret key either way, you will see the following screen on Android.

Enable Google Authenticator on SSH Server

The final step is to integrate Google Authenticator with OpenSSH server. For that, you need to edit two files.

First, edit a PAM configuration file, and append the line below.

$ sudo vi /etc/pam.d/sshd
auth required pam_google_authenticator.so

Then open an SSH server config file, search for ChallengeResponseAuthentication, and enable it.

$ sudo vi /etc/ssh/sshd_config
ChallengeResponseAuthentication yes

Finally, restart SSH server.

On Ubuntu, Debian or Linux Mint:

$ sudo service ssh restart

On Fedora:

$ sudo systemctl restart sshd

On CentOS or RHEL:

$ sudo service sshd restart

Test Two-factor Authentication

Here is how you use two-factor authentication for SSH logins.

Run Google Authenticator app on Android to obtain one-time verification code. Once generated, a given passcode is valid for 30 seconds. Once it expires, Google Authenticator will automatically generate a new one.

Now log in to the SSH server as you normally do.

$ ssh user@ssh_server

When you are asked to enter "Verification code", type in the verification code generated by Android. After successful verification, then you can type in your SSH login password.

To conclude, two-factor authentication can be an effective means to secure password authentication by adding an extra layer of protection. You can use Google Authenticator to secure other logins such as Google account, WordPress.com, Dropbox.com, Outlook.com, etc. Whether you decide to use it or not, it's up to you, but there is a clear industry trend towards the adoption of two-factor authentication.

Subscribe to Xmodulo

Do you want to receive Linux FAQs, detailed tutorials and tips published at Xmodulo? Enter your email address below, and we will deliver our Linux posts straight to your email box, for free. Delivery powered by Google Feedburner.

The following two tabs change content below.
Dan Nanni is the founder and also a regular contributor of Xmodulo.com. He is a Linux/FOSS enthusiast who loves to get his hands dirty with his Linux box. He likes to procrastinate when he is supposed to be busy and productive. When he is otherwise free, he likes to watch movies and shop for the coolest gadgets.
Your name can also be listed here. Write for us as a freelancer.

9 thoughts on “How to set up two-factor authentication for SSH login on Linux

  1. Excellent guide! Do you know how much the mobile app will consume battery? I mean is it generating those codes backgroud even though I haven't opened the app itself.

    • According to my test, when I close Google Authenticator in the foreground, it does not seem to run in the background. You can verify that by looking at cached processes in the Settings.

  2. I followed these steps and I think I'm missing something because I can cancel out of the request for the verification code and just type my login password OR I can type the verification code and then my ssh password.
    I'm using Centos 6.5 running OpenSSH_5.3p1, OpenSSL 1.0.1e-fips 11 Feb 2013. I installed google-authenticator via yum. I ssh into the box via SSH Secure Shell client from windows but I've tried other clients with same results.

    • What exactly do you mean by "cancel out of the request for the verification code"? You should enter the verification code and SSH password correctly, and only then can you log in.

      • What I mean, and again I must be missing something, is that using the client above I got a prompt to put my verification code (expected), I can press the cancel button which immediately prompts for my ssh password which then allows me to login no problem..completely skipping the verification code... Today it's not even asking me for my verification code when I ssh into it from another linbox it just prompts me for my ssh password...weird? I've restarted sshd but no change. It feels like it was a one time deal as when initially adding the "known hosts" when ssh'ing for the first time. Should I reinstall from scratch and report back?

        Thanks!

  3. I may have missed this point, does do you need to be online to use this system? Or can it be run entirely offline (once the software has been installed)?

  4. Thank you for this tutorial.

    I'm afraid I've an issue too as follows:
    Following all steps of the tutorial (double checked everything) I tried to login via ssh and got a prompt for my users password as usual what worked fine besides there was no prompt for the verification code.

    First of all i decided to put the line "auth required pam_google_authenticator.so" not to the end of the file "/etc/pam.d/sshd" but below the other "auth required" lines (last one is "auth required pam_env.so envfile=/etc/default/locale" for me).

    Furthermore I reviewed all changes in the configuration an found "usePAM" set to "no" at the very and of "/etc/ssh/sshd_config". I changed this to "yes" and now there's a prompt for the expected authentication code.

    As a result I now get:
    1. A prompt for the authentication code (expected)
    2. A prompt for "password" (unexpected as I have no idea what password it's supposed to mean, see 3.)
    3. A prompt for my user password (expected)

    Apart from the result "Permission denied, please try again." there is another unexpected behaviour:
    The prompts 1. and 2. are displayed repeatedly as follows:

    > client:~ myaccount$ ssh 192.168.7.2 -l user1
    > Verification code:
    > Password:
    > Verification code:
    > Password:
    > Verification code:
    > Password:
    > user1@192.168.7.2's password:
    > Permission denied, please try again.
    > user1@192.168.7.2's password:
    > client:~ myaccount$

    I've no idea what's going on here.
    I'd really appreciate your support! Thanks in advance!

  5. I'm having the same problem as SR above. I am now completely locked out of my system. It keeps prompting me. I'm to the point where I get locked out every 6 minutes and can't figure out how to get into my system. I've used 2FA on every other site with no problem until I tried to set it up myself with your guide.

  6. Nice guide, works as expected for me, no problems at all. However, is it possible to disable two-step verification for login-attempts from the internal network ip-range?

Leave a comment

Your email address will not be published. Required fields are marked *

Current ye@r *