Two-Factor Authentication for SSH

    Add an essential security layer with TOTP verification for SSH access

    Overview

    Two-factor authentication (2FA) adds an essential security layer to SSH access by requiring both your password (or SSH key) and a time-based one-time password (TOTP) generated by an authenticator app. This guide walks through configuring the Google Authenticator PAM module on Linux servers.

    DifficultyIntermediate
    Time Required15-20 minutes
    Supported OSUbuntu 20.04/22.04/24.04, Debian 11/12, CentOS/RHEL 8/9, AlmaLinux 8/9
    RequirementsRoot/sudo access, TOTP authenticator app

    Prerequisites

    Before you begin, ensure you have the following:

    • Root or sudo access to your server
    • A TOTP-compatible authenticator app installed on your mobile device (Google Authenticator, Authy, Microsoft Authenticator, or 1Password)
    • An active SSH session (keep this open throughout the configuration process)
    • A backup access method (console access via your hosting provider) in case of configuration errors

    Important

    Keep your current SSH session open until you have verified the new configuration works. Misconfigured 2FA can lock you out of your server.

    Installation

    Step 1: Install Google Authenticator PAM Module

    Install the Google Authenticator PAM module using your distribution's package manager.

    Ubuntu/Debian

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

    CentOS/RHEL/AlmaLinux

    sudo dnf install epel-release -y
    sudo dnf install google-authenticator -y

    Configure TOTP

    Step 2: Configure TOTP for Your User Account

    Run the Google Authenticator setup as the user who will be using 2FA (do not use sudo for this step):

    google-authenticator

    You will be prompted with several configuration questions. Here are the recommended responses:

    QuestionAnswerPurpose
    Do you want authentication tokens to be time-based?yUses TOTP standard
    Do you want me to update your ~/.google_authenticator file?ySaves configuration
    Do you want to disallow multiple uses of the same token?yPrevents replay attacks
    Do you want to increase the time skew window?nDefault window is secure
    Do you want to enable rate-limiting?yPrevents brute force

    The setup will display a QR code and a secret key. Scan the QR code with your authenticator app and securely store the emergency backup codes.

    Configure PAM

    Step 3: Configure PAM for SSH

    Edit the PAM configuration file for SSH:

    sudo nano /etc/pam.d/sshd

    Add the following line at the end of the file:

    auth required pam_google_authenticator.so nullok

    The nullok option allows users who haven't configured 2FA to still log in with just their password. Remove nullok once all users have set up their authenticators to enforce 2FA for everyone.

    Configure SSH Daemon

    Step 4: Configure SSH Daemon

    Edit the SSH daemon configuration:

    sudo nano /etc/ssh/sshd_config

    Locate and modify the following directives (or add them if they don't exist):

    ChallengeResponseAuthentication yes
    UsePAM yes

    For Password + TOTP Authentication

    To require both password and TOTP verification:

    AuthenticationMethods keyboard-interactive

    For SSH Key + TOTP Authentication

    To require both an SSH key and TOTP verification:

    AuthenticationMethods publickey,keyboard-interactive

    For SSH key + TOTP, also comment out the following line in /etc/pam.d/sshd:

    # @include common-auth

    Step 5: Restart SSH Service

    Apply the configuration changes by restarting the SSH daemon:

    sudo systemctl restart sshd

    Your existing SSH session will remain active. Test the new configuration in a separate terminal window before closing your current session.

    Test the Configuration

    Step 6: Test the Configuration

    Open a new terminal window (keep your current session open) and test the login:

    ssh username@your-server-ip

    You should be prompted for your password (if using password authentication) followed by the verification code from your authenticator app.

    Backup and Recovery

    Emergency Backup Codes

    During the initial setup, you received five emergency scratch codes. These are one-time use codes that work when you don't have access to your authenticator app.

    • 1.Store these codes in a secure location (password manager, encrypted file, or printed in a safe)
    • 2.Each code can only be used once
    • 3.Generate new codes by re-running google-authenticator if you run out

    Regenerating Codes

    To generate a new set of backup codes without changing your secret key:

    google-authenticator -s ~/.google_authenticator

    Troubleshooting

    Verification Code Not Accepted

    • Time synchronization: Ensure your server's time is accurate. Run timedatectl to check and sudo timedatectl set-ntp true to enable NTP sync.
    • Time zone mismatch: Verify both your phone and server are using correct time zones.
    • Code expiration: TOTP codes are valid for 30 seconds. Wait for a new code if near expiration.

    Locked Out of Server

    View Debug Logs

    Check authentication logs for detailed error information:

    Ubuntu/Debian

    sudo tail -f /var/log/auth.log

    CentOS/RHEL/AlmaLinux

    sudo tail -f /var/log/secure

    Security Best Practices

    • Remove nullok after setup

      Once all users have configured 2FA, remove the nullok option from the PAM configuration to enforce 2FA for all accounts.

    • Use SSH keys with 2FA

      Combining SSH key authentication with TOTP provides the strongest security.

    • Disable root login

      Set PermitRootLogin no in /etc/ssh/sshd_config and use sudo for administrative tasks.

    • Secure backup codes

      Store emergency codes in a password manager or encrypted storage, not in plaintext.

    • Regular audits

      Periodically review /var/log/auth.log for failed authentication attempts.

    • Use Fail2Ban

      Deploy Fail2Ban to automatically block IPs with repeated failed login attempts.

    Conclusion

    Two-factor authentication significantly enhances your server's security by requiring attackers to compromise both your credentials and your physical authenticator device. Combined with strong passwords, SSH key authentication, and regular security updates, 2FA forms an essential layer of your defense-in-depth security strategy.