Skip to main content
Back to Category

SSH 2FA Setup: Security with Google Authenticator

Set up two-factor authentication (2FA) for SSH access. Google Authenticator PAM module, TOTP setup for SSH, backup codes, testing, and troubleshooting guide.

Read time: 12 min Security
2fatwo-factor authenticationgoogle authenticatortotpssh securitypamlinuxmfa

Table of Contents

SSH 2FA Setup: Security with Google Authenticator

While using SSH keys improves security, two-factor authentication (2FA) provides an extra security layer. Even if someone obtains your SSH key, they cannot access the system without the 2FA code. This guide walks you through setting up TOTP-based 2FA for SSH using the Google Authenticator PAM module.

Why is 2FA Important?

  • Stolen key protection: Even if SSH key is stolen, 2FA code is still required
  • Brute-force resistance: Password + 2FA combination is much stronger
  • Compliance: Standards like PCI-DSS and HIPAA require 2FA
  • Easy setup: Can be activated in minutes

Requirements

  • Linux server (Ubuntu/Debian/CentOS)
  • Smartphone (Google Authenticator, Authy, or similar app)
  • Existing SSH access

Don't close your existing SSH connection during 2FA setup. Test from a new terminal after each step. Incorrect configuration can completely block server access.

Installing Google Authenticator PAM Module

hljs bash
# Ubuntu/Debian
sudo apt update
sudo apt install libpam-google-authenticator -y

# CentOS/AlmaLinux
sudo dnf install epel-release -y
sudo dnf install google-authenticator -y

TOTP Setup

hljs bash
# Run as the user you want to enable 2FA for
google-authenticator

When the command runs, you'll be asked:

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

At this point, a QR code and secret key will be displayed. Scan the QR code with the Google Authenticator app.

Do you want me to update your "/home/user/.google_authenticator" file? (y/n) y

Do you want to disallow multiple uses of the same authentication token? (y/n) y

Do you want to increase the window size? (y/n) n

Do you want to enable rate-limiting? (y/n) y

Saving Backup Codes

During setup, 5 backup codes are displayed. Store these in a safe place:

Your emergency scratch codes are:
  12345678
  87654321
  11223344
  44332211
  99887766

Store backup codes in a safe place (password manager, paper, etc.). If you lose your phone, these codes will be your only way in.

PAM Configuration

hljs bash
# Edit SSH PAM configuration
sudo nano /etc/pam.d/sshd
# Add at the beginning of /etc/pam.d/sshd:
auth required pam_google_authenticator.so

Adding the nullok option allows users without 2FA set up to log in with password only. Useful during transition: auth required pam_google_authenticator.so nullok

SSH Configuration

hljs bash
sudo nano /etc/ssh/sshd_config
# Enable keyboard-interactive authentication
ChallengeResponseAuthentication yes

# Set authentication methods
# Option 1: 2FA only (password + TOTP)
AuthenticationMethods keyboard-interactive

# Option 2: SSH key OR 2FA
# AuthenticationMethods publickey keyboard-interactive

# Option 3: SSH key AND 2FA (most secure)
AuthenticationMethods publickey,keyboard-interactive

# UsePAM must be enabled
UsePAM yes
hljs bash
# Restart SSH service
sudo systemctl restart sshd

Most secure configuration: requires SSH key AND 2FA code.

hljs bash
sudo nano /etc/ssh/sshd_config
# SSH key + 2FA required
AuthenticationMethods publickey,keyboard-interactive
PasswordAuthentication no
ChallengeResponseAuthentication yes
UsePAM yes
hljs bash
# PAM configuration
sudo nano /etc/pam.d/sshd
# Comment out password authentication:
# @include common-auth

# Add 2FA
auth required pam_google_authenticator.so

Testing

hljs bash
# Open a new terminal and try to connect
ssh user@server_ip

# Expected output:
# Verification code: (enter code from Google Authenticator)
# Authenticated with partial success.
# (in SSH key + 2FA mode)

Troubleshooting

2FA Code Not Accepted

hljs bash
# Check server time
date
timedatectl

# NTP synchronization
sudo apt install ntp -y
sudo systemctl restart ntp

# Check timezone
timedatectl list-timezones | grep UTC
sudo timedatectl set-timezone UTC

Recovery When Locked Out

hljs bash
# Connect via console access
# Check Google Authenticator file
cat ~/.google_authenticator

# Temporarily disable 2FA
# Comment out pam_google_authenticator line in /etc/pam.d/sshd
sudo nano /etc/pam.d/sshd
# Add # before: auth required pam_google_authenticator.so

sudo systemctl restart sshd

Exempting Specific Users from 2FA

hljs bash
sudo nano /etc/pam.d/sshd
# Exempt specific groups
auth [success=1 default=ignore] pam_succeed_if.so user ingroup notp
auth required pam_google_authenticator.so
hljs bash
# Create notp group and add user
sudo groupadd notp
sudo usermod -aG notp deploy_user

Multi-Server Management

hljs yaml
# Ansible playbook for bulk installation
- name: Install Google Authenticator
  hosts: all
  tasks:
    - name: Install package
      apt:
        name: libpam-google-authenticator
        state: present
    
    - name: PAM configuration
      lineinfile:
        path: /etc/pam.d/sshd
        line: 'auth required pam_google_authenticator.so'
        insertbefore: BOF

Apps like Authy or 1Password offer cloud backup and multi-device support compared to Google Authenticator. Consider these alternatives for enterprise environments.

Conclusion

Setting up 2FA for SSH significantly improves server security. With the Google Authenticator PAM module, you can activate TOTP-based 2FA in minutes. The SSH key + 2FA combination forms one of the strongest authentication methods available.