Hardening SSH with OTP for 2 factor authentication

Something I’ve been meaning to do for a while is look into the possibility of using 2 factor authentication, or 2FA, with SSH connections. This would add a much needed level of security to servers I host out in the wild.

Here’s how I did it:

The Google Authenticator mobile app used to be an open source project, it isn’t any more but the project has been kindly forked and looked after by Red Hat under the guise of the FreeOTP project. The first step is to download the app, which is available for Android and iOS there is even a Pebble project in the works. https://fedorahosted.org/freeotp/

Google Play: https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp

iTunes: https://itunes.apple.com/us/app/freeotp/id872559395

Next we need to configure PAM, this is the component in Linux which ties authentication together. It allows us to add modules for various authentication sources into various applications which require authentication, in this case we need a module compatible with FreeOTP to provide authentication to SSH.

We’ll be using the pam_oath for this, the OATH toolkit is designed for building one-time password based systems. http://www.nongnu.org/oath-toolkit/

yum install pam_oath oathtool gen-oath-safe

This gives us the tools needed to link in to pam, and also generate the initial keys to share between the devices.

Next we need to edit /etc/pam.d/ssh to recognise this module by adding the following line to the top:

auth sufficient pam_oath.so usersfile=/etc/liboath/users.oath window=10 digits=6

Notice we specify a users file, this is where the users who harness OTP will have their details stored. Once this is saved we need to restart sshd

service sshd restart


systemctl restart sshd

So thats ssh configured, from now on when a user logs into the system via ssh, they will be prompted for a One-time password.

Next up we need to generate the keys which are to be shared between the target host (SSH) and the client generating the OTP (Android or iOS app)

gen-oath-safe jon hotp

Replacing jon with your username. hotp denotes the type of key to be generated, hotp being a counter based key and totp being a time based – choice is yours here.

This command will generate a number of codes, HEX, b32, QR and yubikey. The keys we are interested in are the HEX and the QR:


From the app select the QR scanning option on the top tool bar:


Scan the generated QR code which will then store the key in the application.

The final step is to add the HEX code to the file we referenced earlier in the sshd pam config file. Drop the following line /etc/liboath/users.oath (making sure you use your generated key and username):

HOTP jon -  da50cc2e1ee6726c847c5b960a62751e9bbea3a9

Once that file is saved we can go ahead and login via ssh with the specified user. You will now be prompted for a One-time password which can be generated by pressing on the entry within FreeOTP.

Note: if ssh keys are setup then these will be preferred over OTP, i’m sure a modification of the pam config would allow for both but haven’t spent any more time on this yet.




  • Thank you, exactly what I was looking for. Can’t wait to try this at home. 🙂

  • brijesh jaiswal

    The perfect OTP solution. I have tried and now its successful working. The only pre requirement its has is to add third party repositories for installation of pam_oath oathtool gen-oath-safe. Thanks a lot Sir.

  • makefu

    Please Note: This tutorial does not harden your your SSHD by introducing a second factor but it merely replaces the password with a six-digit time-based one time password.

    If you want a second factor for password based authentication replace “auth sufficient” with “auth requisite”. With the next ssh login both the OTP and the plain password will be required.

    Key-Based authentication will “just work” without the second factor if you have it enabled in /etc/ssh/sshd_config .