Introduction

One of the secure login method in linux based system is Key Based Authentication. Key authentication provides cryptographic strength that even extremely long passwords can not offer. With SSH, public key authentication improves security considerably as it frees the users from remembering complicated passwords (or worse yet, writing them down). User has private key in his laptop / desktop and public key will be pushed to destination server. This key can be protected with a password for extra layer of protection.

Is this still secure, what if your laptop / desktop can be stolen or got access to a bad guy? In this article, i am explaining how to add 2FA / MFA for your SSH logins. This means a bad guy would have to compromise more than one devices, like both your computer and your phone, to get in. The different type of factors are often summarized as:

  • Something you know, like a password or security question
  • Something you have, like an authenticator app or security token
  • Something you are, like your fingerprint or voice

Prerequisitess

  • Debian 10
  • Smartphone with Google Authenticator installed iOS OR Android

Install Google’s PAM

sudo apt-get update
sudo apt-get install libpam-google-authenticator

Intialization

google-authenticator

When you run the command, it will ask for few questions.

Do you want authentication tokens to be time-based (y/n) y

After press Y, a large QR code will be displayed on your screen. Scan it using your TOTP app in the mobile phone.

The remaining questions are

Do you want me to update your "~/.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) y

Configuring PAM

sudo vim /etc/pam.d/sshd

Add the below at the end of file

. . .
# Standard Un*x password updating.
@include common-password
auth required pam_google_authenticator.so nullok

the nullok parameter tells the PAM is that 2FA is optional only. Which means still users can login without 2FA. Once everyone has 2FA enabled, we can remove nullok

Configuring OpenSSH

sudo vim /etc/ssh/sshd_config

Look for ChallengeResponseAuthentication and set its value to yes.

. . .
# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
ChallengeResponseAuthentication yes
...

Restart service

sudo systemctl restart sshd.service

Making SSH Aware of MFA

sudo vim /etc/ssh/sshd_config
. . .
UsePAM yes
AuthenticationMethods publickey,password publickey,keyboard-interactive
sudo vim /etc/pam.d/sshd

Find the line @include common-auth and comment it out by adding a #

. . .
# Standard Un*x authentication.
# @include common-auth
. . .

Restart the service

sudo systemctl restart sshd.service

Sample output from the client.

. . .
debug1: Authentications that can continue: publickey
debug1: Next authentication method: publickey
debug1: Offering RSA public key: /Users/niceboy/.ssh/id_rsa
debug1: Server accepts key: pkalg rsa-sha2-512 blen 279
Authenticated with partial success.
debug1: Authentications that can continue: password,keyboard-interactive
debug1: Next authentication method: keyboard-interactive
Verification code:

Enter the code from the Google Authenticator, and you are in. Security Matters