Blog · WebJi® India

SSH Two-Factor Authentication

Quick answer: SSH two-factor authentication adds a one-time code to the login. Install libpam-google-authenticator, add auth required pam_google_authenticator.so to /etc/pam.d/sshd, set KbdInteractiveAuthentication yes and UsePAM yes, then register the account with google-authenticator. Test in a second session and keep the scratch codes before you close the first.
✓ In business since 2005✓ INR + GST billing✓ 24/7 Email Support — avg reply < 60 min
Indian trader monitoring candlestick charts on multiple screens in evening light — ssh two factor authentication

What the second factor adds

SSH two-factor authentication adds a one-time code to the login. Install libpam-google-authenticator, add auth required pam_google_authenticator.so to /etc/pam.d/sshd, set KbdInteractiveAuthentication yes and UsePAM yes, then register the account with google-authenticator. Test in a second session and keep the scratch codes before you close the first.

The key and the code answer two different questions. The key proves the device; the time-based one-time password (TOTP) proves the person holding it. With both required, a stolen laptop or a copied private key is no longer enough on its own.

  • Something you have: the SSH private key or a hardware token.
  • Something you know or hold: the six-digit code from an authenticator app.
  • What it stops: credential stuffing, a leaked key, a reused password.
  • What it does not stop: a phishing site that proxies the code in real time. A hardware key does.

Before you change anything

This is the change that locks administrators out. Ten minutes of preparation removes the risk entirely.

  1. Keep your current SSH session open. It survives the sshd restart and can undo the edit.
  2. Confirm the provider console or rescue mode works before you need it.
  3. Create or confirm a second sudo user, so one broken profile is not fatal. The sudo user guide covers it.
  4. Take a snapshot if the panel offers one.
  5. Know your scratch codes' location before enrolment, because they are printed once.

Install and register the token

The PAM module is in the distribution repositories. Register the token as the login user, not as root, because the secret is stored in that user's home directory.

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

Answer the questions this way: time-based tokens yes, update the file yes, disallow multiple uses yes, increase the time window no, enable rate limiting yes. The command prints a QR code and a list of scratch codes. Store the codes offline; they are the recovery path when the phone is gone.

The secret lives in ~/.google_authenticator. Check that the file is readable only by its owner with chmod 600 ~/.google_authenticator. On RHEL-family systems the package is google-authenticator from EPEL.

Wire PAM and sshd

Two files change: the PAM stack and the sshd configuration. Read both before saving, and test the sshd file before restarting.

  1. Add one line to /etc/pam.d/sshd: auth required pam_google_authenticator.so.
  2. In /etc/ssh/sshd_config set KbdInteractiveAuthentication yes. Older guides say ChallengeResponseAuthentication; it is the deprecated name for the same setting.
  3. Confirm UsePAM yes is present and not commented out.
  4. To require both factors, add AuthenticationMethods publickey,keyboard-interactive.
  5. Run sudo sshd -t, restart with sudo systemctl restart ssh, and open a second session to test.

If the second session asks for a verification code after your key, it worked. If it refuses, go back to the first session and revert the two files; the old session is still authenticated.

Know it worked

Success has three visible signs: the login prompts for a verification code after the key, a wrong code is rejected, and the auth log records the method used.

sudo tail -n 20 /var/log/auth.log
sudo journalctl -u ssh -n 20 --no-pager

Look for Accepted keyboard-interactive/pam next to the successful login. A line saying Accepted publickey alone means the second factor was not required, which usually means the AuthenticationMethods line is missing or misspelled.

Automation accounts need an exemption. A backup job cannot type a code, so give it its own key and a Match User backup block that allows publickey only, rather than weakening the rule for everyone.

Recovery when the phone is lost

A lost phone is not a lost server if you prepared. Work through these in order, from least to most invasive.

  1. Enter one of the scratch codes at the verification prompt. Each works once.
  2. If the codes are gone, open the provider console and log in there.
  3. Move the secret aside: mv ~/.google_authenticator ~/.google_authenticator.bak, then log in with the key alone.
  4. Re-enrol with google-authenticator and store the new scratch codes.
  5. If sshd itself will not start, set AuthenticationMethods back to publickey, run sshd -t, and restart.

The connection refused guide covers the console and rescue-mode path when SSH is not answering at all.

TOTP, hardware key or both

TOTP is the pragmatic default: any phone, no extra hardware, one extra prompt. A hardware key is stronger against phishing but needs to be bought and carried. Many teams use a key for administrators and TOTP for everyone else.

MethodWhat the user needsPhishing resistanceFits
Password onlyNothing extraNoneNowhere on a public VPS
Key onlyA key fileGood, unless the key is copiedAutomation and most admins
Key plus TOTPA key and a phone appStrong against stolen keysProduction servers, small teams
Key plus hardware tokenA key and a FIDO2 deviceStrongest; resists real-time phishingAdministrators of critical systems

Whatever you choose, turn off password authentication only after the new method has worked in a second session. A WebJi VPS includes console access for exactly this kind of change; support@webji.services answers email 24/7 in Hindi and English, average first reply under 60 minutes.

Frequently Asked Questions

How do I enable 2FA for SSH on Ubuntu?

Install libpam-google-authenticator, add auth required pam_google_authenticator.so to /etc/pam.d/sshd, set KbdInteractiveAuthentication yes and UsePAM yes in sshd_config, run google-authenticator as the login user, then restart ssh. Test in a second session before closing the first.

What is the most secure SSH setup?

Key-only login plus a second factor: AuthenticationMethods publickey,keyboard-interactive, password authentication off, root login disabled, and a hardware key where the team can carry one. Each layer covers a different failure.

Can I use Google Authenticator for SSH login?

Yes. The PAM module reads a TOTP secret stored in the user's home directory, and any TOTP app works: Google Authenticator, Aegis, 1Password, Microsoft Authenticator. The server does not depend on Google's service.

Should I use SSH keys and 2FA together?

Yes, when the server matters. The key proves the device and the code proves the person. Requiring both means a stolen laptop or a copied key alone is not enough to log in.

What if I lose my 2FA device for SSH access?

Use one of the scratch codes printed during enrolment, then log in and re-enrol the new phone. Without a scratch code, use the provider console or rescue mode to move .google_authenticator aside, log in, and enrol again.

Does fail2ban work with SSH 2FA?

Yes, and it complements it. fail2ban blocks repeated failed attempts at the network level; 2FA blocks a valid password or key from completing the login. Whitelist your admin IP in fail2ban before you enable 2FA.

Need help with this?

WebJi® support does it for you — free. Talk to our Jaipur team →