Two-factor authentication for SSH

September 29, 2019 devadvin

I recently received access to some impressive hardware. I put it on the internet and within less than 24 hours someone had already gotten in. Honestly, I did set the ssh password to P@ssw0rd! but still! Less than 24 hours? Come on, script kiddies! Give me at least 24 hours to set up.

So, because of this, I decided that I needed to lock down my internet facing machines. First, I had
to make some changes to the main /etc/ssh/sshd_config file to secure the machine. I changed the file to include:

PermitRootLogin no
PasswordAuthentication no

I copied my main to the authorized_keys of my user on the box. I enabled sudo for it and now I feel much safer. But, that isn’t what this post is about. It’s about those times I need to knock on the front door and get access to this machine. This is where two-factor authentication (2FA), an extra layer of security, is helpful.

There’s a handful of options and open source projects to do 2FA, but I’ve decided to try using the libpam-google-authenticator, which you can find the code for here.

Before I go any further, this blog is a Voltron-like walkthrough from:

I’d like to thank the individuals behind this work. Without them, I would have never gotten this to work.

Configure your application

To get the keys created, every user has to run the authentication software. There is a way to use something like Chef or Ansible for automation, but that’ll come at the end of this post. For now, let’s just get it working with one user or administrator.

I have my brand new machine up and running:


First, I have to install the software. I’m on Debian, but you can install your packages using something like this:

admini@debian-template:~$ sudo apt-get update \
&& sudo apt-get install libpam-google-authenticator

Hopefully, there are no errors. We now have the application installed.

Next, let’s run the application:

admini@debian-template:~$ google-authenticator

Do you want authentication tokens to be time-based (y/n) y
Warning: pasting the following URL into your browser exposes the OTP secret to Google:|0&cht=qr&chl=otpauth://totp/admini@debian-template%3Fsecret%3DKQ35JFEFTLDB3TA7QZILK4N7UE%26issuer%3Ddebian-template

[-- A QR CODE --]

Your new secret key is: KQ35JFEFTLDB3TA7QZILK4N7UE
Your verification code is 994945
Your emergency scratch codes are:

Do you want me to update your "/home/admini/.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, a new token is generated every 30 seconds by the mobile app.
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. This allows for a
time skew of up to 30 seconds between authentication server and client. If you
experience problems with poor time synchronization, you can increase the window
from its default size of 3 permitted codes (one previous code, the current
code, the next code) to 17 permitted codes (the 8 previous codes, the current
code, and the 8 next codes). This will permit for a time skew of up to 4 minutes
between client and server.
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

Now, you want to choose y for the first question, or the application won’t work. You should answer y for the second question too, as it is a good practice for passwords to expire every 30 seconds. Now, save the emergency scratch codes in a trusted location. If you can’t take a picture of the QR code, use the secret key and verification code manually. (But, you should be able to take a picture.)

You shouldn’t share your tokens, so y is a good option for question number three. Answering y on the fourth and fifth questions is also a good practice.

Congrats! You’ve successfully configured the application.

Enable 2FA

Now, let’s link the application up to ssh. We need to edit the /etc/pam.d/sshd file. You’ll need to be root which requires you to run the command line sudo su.

admini@debian-template:~$ sudo su -
root@debian-template:~# vi /etc/pam.d/sshd

Go ahead and add this to the top of the file:

auth required

Comment out the following if you don’t want a password check:

#@include common-auth

Write and quit the file. Now, open up:

root@debian-template:~# vi /etc/ssh/sshd_config

Change the following line to:

ChallengeResponseAuthentication yes

Then, add this to the file:

AuthenticationMethods publickey keyboard-interactive

If you want to be really secure you can add a comma between it to make sure that you have both your on the account and your 2FA enabled. I’d only do this after you’ve got your publickey on the box, otherwise, you’ll get errors when attempting to reconnect.

An example with the comma would look like this:

AuthenticationMethods publickey,keyboard-interactive

Now it’s time to validate your /etc/ssh/sshd_config via:

root@debian-template:~# sshd -t

If any errors appear, go ahead and fix them now. If not, restart sshd.

root@debian-template:~# systemctl reload sshd.service

Go ahead and logout and then log back in. You should see something like this:

~ > ssh admini@
Verification code:
Linux debian-template 4.19.0-5-amd64 #1 SMP Debian 4.19.37-5 (2019-06-19) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Wed Aug  7 19:39:27 2019 from

Congratulations! You now have 2FA working on your machine.

Use automation to configure your application

If you would like to automate this with a Chef Cookbook or Ansible playbook, you can! You can run all the questions via a command line. If you run google-authenticator --help you can see all your options:

admini@debian-template:~$ google-authenticator --help
google-authenticator [<options>]
 -h, --help                     Print this message
 -c, --counter-based            Set up counter-based (HOTP) verification
 -t, --time-based               Set up time-based (TOTP) verification
 -d, --disallow-reuse           Disallow reuse of previously used TOTP tokens
 -D, --allow-reuse              Allow reuse of previously used TOTP tokens
 -f, --force                    Write file without first confirming with user
 -l, --label=<label>            Override the default label in "otpauth://" URL
 -i, --issuer=<issuer>          Override the default issuer in "otpauth://" URL
 -q, --quiet                    Quiet mode
 -Q, --qr-mode={NONE,ANSI,UTF8} QRCode output mode
 -r, --rate-limit=N             Limit logins to N per every M seconds
 -R, --rate-time=M              Limit logins to N per every M seconds
 -u, --no-rate-limit            Disable rate-limiting
 -s, --secret=<file>            Specify a non-standard file location
 -S, --step-size=S              Set interval between token refreshes
 -w, --window-size=W            Set window of concurrently valid codes
 -W, --minimal-window           Disable window of concurrently valid codes
 -e, --emergency-codes=N        Number of emergency codes to generate

You’ll have to add this for each of your users on the machine. However, it is possible to automate the setup.


You’ve successfully added an additional level of security to your machine. Going forward, you’ll probably agree that two means of identification are better than one. However, I still wouldn’t recommend setting your password to P@ssw0rd! though!

Previous Article
Introducing Node-RED 1.0
Introducing Node-RED 1.0

Open sourced by IBM 6 years ago, Node-RED reaches the major milestone of its 1.0 release.

Next Article
Let’s talk modern development at SpringOne Platform
Let’s talk modern development at SpringOne Platform

Join us at SpringOne Platform 2019 for an incredible line-up of speakers and a fun, hands-on quicklab, all ...


Want our latest news? Subscribe to our blog!

Last Name
First Name
Thank you!
Error - something went wrong!