Two Factors Are Better Than One

Configure User Accounts

I recommend setting up Google Authenticator for all of your user accounts (or at least all of the sysadmin accounts) before enforcing 2FA in SSH to make it easier to enroll all of the users and avoid the risk of locking people out. To configure Google Authenticator, each user needs to log in and run google-authenticator. You will be presented with a series of questions where it's safe to answer "y"; however, I generally answer no to extending the time window to four minutes, and I also answer no to rate limiting, since as I disable password authentication, I'm less concerned with brute-force attacks. The output looks something like this:

$ google-authenticator

Do you want authentication tokens to be time-based (y/n) y|0&cht=qr&chl
QR Code Removed
Your new secret key is: 4SK2LTLCTLCEV757
Your verification code is 221544
Your emergency scratch codes are:

Do you want me to update your "/home/username/.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) n

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) n

If you have libqrencode installed, the output also will contain a QR code in the console you can scan with the Google Authenticator app on your phone. Otherwise, you simply can enter the secret key into your Google Authenticator application on your phone. Also, be sure to write down those backup codes and store them in a safe place. These are one-time-use codes you can use to get back in to the system in case you ever lose or wipe your phone. Once you are logged back in, you can run google-authenticator again.

Configure PAM and SSH

Once your phone and user accounts are configured with Google Authenticator, you are ready to enforce 2FA in PAM and SSH. To do this, edit your /etc/pam.d/sshd file and add the following to the top of the file:

auth required

On my Debian system, I noticed that once I finished the configuration process, I would not only be prompted for my 2FA token, I'd also be prompted for my local system password. Because I wasn't interested in three-factor authentication (two-and-a-half factor authentication?), I noticed I needed to comment out the following further down in the file:

@include common-auth

Of course, if you aren't on a Debian-based system, this extra step may not be necessary.

The final step is to configure SSH. Hopefully you already have disabled password authentication for SSH in the past, and if not, I recommend you consider it. Most of the SSH 2FA guides out there (this one included) will tell you to enable ChallengeResponseAuthentication in your /etc/ssh/sshd_config:

ChallengeResponseAuthentication yes

I noticed, however, that when you are using key-based authentication instead of passwords, you need to add an additional setting to the config file:

AuthenticationMethods publickey,keyboard-interactive

Once these settings are in place, you can enable them by restarting your SSH service, which depending on your system may be one of the following:

$ sudo service ssh restart
$ sudo service sshd restart

After SSH has restarted, you should get an additional prompt the next time you SSH to the server:

$ ssh
Authenticated with partial success.
Verification code:

Type in the verification code that shows up in your Google Authenticator phone app, and you can log in. The nice thing about adding 2FA to SSH is that it provides an additional means of protection in case your computer is ever compromised or stolen. Attackers also would have to compromise or steal your phone before they could access your systems.


Kyle Rankin is SVP of Security and Infrastructure at Zero, the author of many books including Linux Hardening in Hostile Networks, DevOps Troubleshooting and The Official Ubuntu Server Book, and a columnist for Linux Journal. Follow him @kylerankin