It turns out you can enable 2-Factor Authentication (2FA) login challenges using Google Authenticator combined with SSH public/private key pairs – which is just a great idea in general.
FYI: You DO NOT need a Google account to use Google Authenticator.
This means even if your keys were somehow compromised an attacker still couldn’t get in without physically having your phone with them AND unlocking it.
So unless your good friends or loved ones are trying to hack you, you should be in pretty good shape 🙂
Installing Google Authenticator
There are two halves to the “installing Google Authenticator” step, at a high level:
- Installing it on your phone from the App Store (iOS / Android) – go ahead and do this now. There isn’t any account-creation step, you just install it and then start registering challenges from servers.
- Installing it on your server and setting it up, so it can challenge and confirm people logging in.
#1 you can do right now – it’s a 1-step process.
Now, let’s dig in on the server setup…
Configuring it on the server
First, let’s install the
sudo apt-get install libpam-google-authenticator
After it’s installed, head to your
$HOME directory and run the authenticator to do the setup:
$ cd ~ $ google-authenticator
The setup will ask you a series of questions that look like the following:
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: https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/<your key information> ... A GIANT ASCII QR CODE (COOL!) ... Your new secret key is: <SECRETS!> Your verification code is <CODE> Your emergency scratch codes are: <CODE 1> <CODE 2> <CODE 3> <CODE 4> <CODE 5> Do you want me to update your "/home/rkalla/.google_authenticator" file? (y/n) y Do you want to disallow multiple ... SNIP ... (y/n) y By default, a new token is generated ... SNIP ... (y/n) y If the computer that you are logging into ... SNIP ... (y/n) y
FYI: You need to run
google-authenticator as each user you with to use it for. Right now, in this example, it is only setup for my
Critical Step 1 of 2: Open Google Authenticator on your app, click the “+” button and register using a QR code – point your phone at the giant ASCII QR code on your screen.
If you are unable to capture the QR code, register using the “secret key” that is printed out in the terminal right under the QR code and in the Google Auth app.
Critical Step 2 of 2: Backup the 5 “emergency scratch codes” somewhere safe (like a Password Wallet) – these are the codes you can use if you lose your phone or the Google Auth app won’t work any longer.
Excellent, now you have:
- (Server) Google Authenticator installed
- (Server) Google Authenticator configured for the user
- (Mobile) Google Authenticator installed
- (Mobile) Google Authenticator linked to the configured
rkallauser on the server.
There is one more thing we need to do…
Connecting Google Auth and the SSH Daemon
Now that everything is ready to go, the last step is to connect the SSH Daemon to the Google Authenticator library to ensure it challenges users with an auth code on login.
First, let’s edit the daemon config:
sudo nano /etc/ssh/sshd_config
Search the file for
ChallengeResponseAuthentication, I found it around Line 69 in my config.
The default setting is typically
no – change it to
yes so it looks like this:
# Change to yes to enable challenge-response passwords (beware issues with # some PAM modules and threads) ChallengeResponseAuthentication yes
Before you leave, search for the
UsePAM setting and ensure it is set to
Now save the file and exit.
FYI: “PAM” stands for “Pluggable Authentication Module” and is a framework SSH/OpenSSH use to support 3rd party integrations – in this case, Google Authenticator.
Next thing to do is actually modify the PAM configuration for the SSH Daemon:
sudo nano /etc/pam.d/sshd
Near the top of the file (at least on Ubuntu 20.04) you’ll see the lines:
# Standard Un*x authentication. @include common-auth
Then add a required reference to the Google Auth PAM module, so all the lines look like so:
# Standard Un*x authentication. @include common-auth auth required pam_google_authenticator.so
Tip: You can comment out the
common-auth module if you ONLY want an auth code enter for your login. Or you can leave them both uncommented if you want the user asked for BOTH a password and auth code – it’s your choice!
Once you are done with your changes, save the file and exist.
Now restart SSH Daemon to pickup the config changes:
sudo systemctl restart ssh
Now, before you logout of this terminal session, let’s make sure your changes worked!
Open a new terminal and initiate a connection to your server and confirm that you are now being asked for an auth-code and possibly a password (depending on which auth modules you left enabled).
Did it work? Excellent! On to more securing!