Why
Even though SSH is a pretty good security guard for your doors and windows, it is still a visible door that bad-actors can see and try to brute-force in. Fail2ban will monitor for these brute-force attempts but there is no such thing as being too secure. Requiring two factors adds an extra layer of security. Using Two-Factor Authentication (2FA) / Multi-Factor Authentication (MFA) requires anyone entering to have two keys to enter which makes it harder for bad actors:- Their password
- A 6 digit token that changes every 30 seconds
Why Not
Many folks might find the experience cumbersome or annoying. And, access to your system is dependent on the accompanying authenticator app that generates the code.How It Works
On Linux, PAM (Pluggable Authentication Modules) is responsible for authentication. When you log into a server, be it directly from the console or via SSH, the door you came through will send the request to the authentication task of PAM and PAM will ask for and verify your password. You can customize the rules each door uses. For example, you could have one set of rules when logging in directly from the console and another set of rules for when logging in via SSH. This section will alter the authentication rules for when logging in via SSH to require both a password and a 6 digit code. We will use Google’slibpam-google-authenticator PAM module to create and verify a TOTP (Time-based One-Time Password) key.
The Process
- User attempts to login via SSH
- PAM asks for their password and verifies it
- If password is correct, PAM routes the authentication request to
libpam-google-authenticator libpam-google-authenticatorasks for the 6 digit token- If the token is correct, authentication succeeds and user is allowed to log in
Goals
- 2FA/MFA enabled for all SSH connections
Important Notes:
- Before you do this, you should have an idea of how 2FA/MFA works and you’ll need an authenticator app on your phone to continue.
- With the below configuration, a user will only need to enter their 2FA/MFA code if they are logging on with their password but not if they are using SSH public/private keys. Check the documentation on how to change this behavior to suite your requirements.
Steps
Generate authentication tokens
Make sure you’re logged in as the ID you want to enable 2FA/MFA for and execute You’ll see output like:Select default option (y in most cases) for all the questions it asks.Scan the QR code with your authenticator app (Google Authenticator, Authy, etc.) to set up the token.
google-authenticator to create the necessary token data:Configure PAM for SSH
Make a backup of PAM’s SSH configuration file Now enable it as an authentication method for SSH by adding this line to For the lazy (automated approach):
/etc/pam.d/sshd:/etc/pam.d/sshd:The
nullok option means users who haven’t set up 2FA yet can still login. Once all users have set up 2FA, you can remove this option to make 2FA mandatory.Enable challenge-response authentication
Make a backup of SSH’s configuration file Tell SSH to leverage challenge-response authentication by adding or editing this line in For the lazy (automated approach):
/etc/ssh/sshd_config:/etc/ssh/sshd_config:Test 2FA authentication
From a new terminal, try connecting to your server:If you’re using password authentication, you should be prompted for:
- Your password
- Your 6-digit verification code from your authenticator app
Understanding TOTP
TOTP (Time-based One-Time Password) works by:- Shared Secret: When you set up 2FA, a secret key is generated and shared between the server and your authenticator app (via QR code)
- Time-based: The current time is used as an input to generate the code
- Algorithm: The secret key and current time are used with an algorithm to generate a 6-digit code
- Synchronization: Both the server and your app use the same algorithm, so they generate the same code at the same time
- Expiration: Codes expire every 30 seconds, so old codes can’t be reused
Advanced Configuration
Require 2FA for Key-Based Authentication
If you want to require 2FA even when using SSH keys, add this line to/etc/ssh/sshd_config:
Remove nullok to Make 2FA Mandatory
Once all users have set up 2FA, edit/etc/pam.d/sshd and remove nullok from the line:
Troubleshooting
Lost Access to Authenticator App
Use one of your emergency scratch codes to login. Each code can only be used once.Time Synchronization Issues
If codes aren’t working, ensure the server time is accurate:Locked Out
If you’re locked out:- Use your backup SSH session (you kept it open, right?)
- Or use physical/console access to the server
- Edit
/etc/pam.d/sshdand comment out the google-authenticator line - Restart SSH