Hardening SSH

Why SSH Still Matters (and Why It’s Still Attacked)

SSH is the backbone of modern infrastructure administration. Whether you manage cloud workloads, on‑prem servers, Kubernetes nodes, or embedded systems, SSH is still the control plane.

And that’s exactly why it’s relentlessly attacked.

  • Credential stuffing

  • Leaked private keys

  • Reused passwords

  • Forgotten jump hosts

Even with key‑based authentication, a single compromised workstation can become a disaster.

Defense in depth matters. One of the simplest and most effective layers you can add is TOTP‑based multi‑factor authentication using PAM.

This post walks through why and how to add TOTP to SSH without breaking automation or locking yourself out.

What We’re Building

We’ll implement:

  • SSH authentication using:

    • Public key authentication

    • TOTP (Time‑based One‑Time Password)

  • Enforced via PAM (Pluggable Authentication Modules)

  • Compatible with:

    • Google Authenticator

    • FreeOTP

    • Authy (manual entry)

    • Bitwarden

    • Many more….

This setup works on most Linux distributions (Debian, Ubuntu, RHEL, Rocky, Alma).

Threat Model (Quick Reality Check)

This protects against:

  • Stolen SSH private keys

  • Password reuse

  • Brute‑force attacks

  • Lateral movement from compromised hosts

This does not protect against:

  • Root compromise

  • Malicious PAM modules

  • A fully compromised client and unlocked authenticator

Security is layers, not magic.

Step 1 – Install the PAM TOTP Module

On Debian / Ubuntu:

apt install libpam-google-authenticator

On RHEL‑based systems:

dnf install google-authenticator

Yes, the package name is confusing. No, it does not require Google services.

Step 2 – Enroll a User

Run the enrolment as the target user, not root:

google-authenticator

Recommended answers:

  • Time‑based tokens: yes

  • Update ~/.google_authenticator: yes

  • Disallow multiple uses: yes

  • Increase window: no (unless clock drift is an issue)

  • Enable rate‑limiting: yes

Scan the QR code with your authenticator app and store the emergency scratch codes offline.

Step 3 – Configure PAM for SSH

Edit:

/etc/pam.d/sshd

Add at the top:

auth required pam_google_authenticator.so nullok
auth required pam_permit.so

Important Notes

  • nullok allows users without TOTP configured to log in

  • This is useful for:

    • Service accounts

    • Gradual rollouts

You can remove nullok later to enforce TOTP everywhere.

Step 4 – Configure SSHD

Edit:

/etc/ssh/sshd_config

Ensure the following settings:

UsePAM yes
ChallengeResponseAuthentication yes
KbdInteractiveAuthentication yes
AuthenticationMethods publickey,keyboard-interactive

Then reload SSH:

systemctl reload sshd

⚠️ Do not close your existing SSH session yet.

Step 5 – Test Safely

Open a new SSH session and connect.

Expected flow:

  1. SSH key authentication

  2. TOTP prompt

  3. Successful login

If it fails:

Check logs:

journalctl -u sshd -f

Verify file permissions:

chmod 600 ~/.google_authenticator

Automation & Service Accounts (The Right Way)

You should not disable MFA globally just to keep automation working.

Instead:

Option 1 – Dedicated Accounts

  • No TOTP enrollment

  • nullok enabled

  • Restricted via:

    • AllowUsers

    • Match User blocks

    • Forced commands

Option 2 – Match Blocks

Match User deploy

AuthenticationMethods publickey

This keeps humans protected while automation stays predictable.

Common Pitfalls

  • ❌ Forgetting UsePAM yes

  • ❌ Testing in the same SSH session

  • ❌ Locking out root without console access

  • ❌ Enforcing MFA on service accounts

Security should slow attackers, not engineers.

Final Thoughts

TOTP via PAM is one of the highest ROI security improvements you can make to SSH:

  • Minimal complexity

  • No external dependencies

  • No cloud lock‑in

  • Strong protection against real‑world attacks

If SSH is still your control plane — and it is — it deserves MFA.

Next posts will go deeper into:

  • SSH certificates

  • Bastion hosts vs Zero Trust

  • Hardware‑backed SSH keys

  • Breaking legacy authentication safely

Security is not a product. It’s a posture.