Skip to content
Chethan Yadav
Work

Security/2026/Active

SSH 2FA Hardening

Enterprise-grade automation framework to harden Linux SSH access with Google Authenticator PAM-based two-factor authentication.

Shell

Overview

ssh-2fa-hardening is a shell-script framework that automates rolling out Google Authenticator PAM-based two-factor authentication for SSH on Linux — turning a normally fiddly, easy-to-botch manual process (install the PAM module, edit the PAM stack, edit sshd_config, restart the daemon, hope you didn't just lock yourself out) into a single guarded script run.

It's built for sysadmins and DevSecOps teams who need to add a possession factor to SSH access across a fleet of Ubuntu, Debian, CentOS, or RHEL hosts without risking a lockout, and who want the same tooling to verify the change afterward and roll it back cleanly if something goes wrong.

What separates it from a plain apt install libpam-google-authenticator walkthrough is the safety machinery built around the actual PAM/SSH edits: pre-flight checks, idempotent config mutation, a syntax-validation gate before the SSH daemon ever restarts, and a dedicated rollback script tied to timestamped backups.

Key Features

  • One-line deployment — pipe setup.sh straight into sudo bash
  • OS and package-manager detection — supports apt (Ubuntu/Debian) and yum/dnf (CentOS/RHEL)
  • Pre-flight validation — checks run before anything is mutated
  • Timestamped automatic backups — every changed config is backed up before modification
  • Interactive Google Authenticator enrollment — guided QR-code setup with a re-display option if you miss the scan
  • Idempotent PAM/SSH config updates — safe to re-run without creating duplicate directives
  • Syntax-safe validation gate — runs sshd -t before the SSH service is restarted, so a broken config never gets applied
  • Cross-distro service abstraction — handles the ssh/sshd service-name difference between distros
  • Dedicated verify and rollback tooling — separate scripts to confirm the hardening applied correctly or undo it

Installation

curl -sSL https://raw.githubusercontent.com/chethanyadav456/ssh-2fa-hardening/refs/heads/main/setup.sh | sudo bash
wget -qO- https://raw.githubusercontent.com/chethanyadav456/ssh-2fa-hardening/refs/heads/main/setup.sh | sudo bash

Or clone and run locally:

git clone https://github.com/chethanyadav456/ssh-2fa-hardening.git
cd ssh-2fa-hardening
sudo bash setup.sh

Before running: keep your current SSH session open, and validate access from a second terminal before closing the first. The script requires explicit confirmation after QR enrollment, but confirming from within the same session doesn't guarantee a fresh connection will actually authenticate.

How It Works

The framework runs in six controlled phases: pre-checks and dependency readiness, interactive identity-factor enrollment, PAM mutation with backup-aware idempotency, SSH daemon hardening with a compatibility fallback, a syntax-validation gate before any service reload/restart, and a post-change verification and operator-warning flow.

During enrollment, the script generates a QR code for Google Authenticator and blocks on a confirmation prompt:

Have you scanned the QR code?
 
1. Yes, continue
2. Show QR again
3. Exit safely

There's no bypass for this step in the production flow. After PAM and sshd_config are updated, the script runs sshd -t to validate syntax before restarting the SSH service — if validation fails, the daemon is never touched with a broken config.

Verification:

sudo bash verify.sh

Checks package presence, PAM line enforcement, SSH hardening directives, sshd -t validity, and SSH service health.

Rollback:

sudo bash rollback.sh

Restores the latest backup set from /var/backups/ssh-2fa-hardening/ and attempts a safe SSH service restart.

View on GitHub ↗