How to Set Up Two-Factor Authentication for SSH with Google Authenticator on RHEL 7
Password-based SSH authentication is vulnerable to brute-force attacks, credential stuffing, and phishing. Adding a second authentication factor — a time-based one-time password (TOTP) generated by an app like Google Authenticator or Authy — dramatically reduces this risk. Even if an attacker steals or guesses a password, they cannot log in without the six-digit code from the user’s phone. This guide explains how to install the Google Authenticator PAM module on RHEL 7, configure PAM and the SSH daemon to require both a password and a TOTP code, and test the complete two-factor flow.
Prerequisites
- RHEL 7 server with root or
sudoaccess - EPEL repository enabled
- A smartphone with Google Authenticator, Authy, or any TOTP-compatible app installed
- An active SSH session — do not close it until you have verified the new configuration works, or you risk locking yourself out
Step 1: Enable the EPEL Repository
The google-authenticator-libpam package is distributed through EPEL. If EPEL is not already enabled, install it:
yum install epel-release -y
Verify the repository is active:
yum repolist | grep epel
Step 2: Install the Google Authenticator PAM Module
yum install google-authenticator -y
This installs both the pam_google_authenticator.so shared library and the google-authenticator setup binary. Confirm the PAM module is present:
ls -l /usr/lib64/security/pam_google_authenticator.so
Step 3: Configure Google Authenticator for Each User
Each user who will authenticate via SSH must run the google-authenticator command in their own account. Log in as (or switch to) the target user before running this step. Do not run it as root unless root SSH login is specifically required.
su - exampleuser
google-authenticator
The wizard asks a series of questions. Recommended answers for most environments:
- Do you want authentication tokens to be time-based? —
y(enables TOTP) - A QR code is displayed in the terminal. Scan it with your authenticator app immediately.
- Do you want me to update your ~/.google_authenticator file? —
y - Disallow multiple uses of the same authentication token? —
y(prevents replay attacks) - Increase window from 1:30 to 4 minutes? —
n(only say yes if clock skew is a known problem) - Enable rate limiting? —
y(limits brute-force attempts on OTP codes)
After the wizard completes, a ~/.google_authenticator file is created for the user containing the secret key and emergency scratch codes. Store the scratch codes securely — they are single-use backup codes for account recovery.
cat ~/.google_authenticator
The first line is the base32-encoded secret. Following lines contain options and scratch codes.
Step 4: Configure PAM for SSH
Edit the PAM configuration file for the SSH daemon:
cp /etc/pam.d/sshd /etc/pam.d/sshd.bak
vi /etc/pam.d/sshd
Add the following line at the very top of the file, before any other lines:
auth required pam_google_authenticator.so nullok
The nullok option allows users who have not yet run google-authenticator to log in with just a password. Once all users have set up TOTP, remove nullok to make the second factor mandatory for everyone. The full beginning of the file should look like this:
auth required pam_google_authenticator.so nullok
auth required pam_sepermit.so
auth substack password-auth
auth include postlogin
Save and close the file.
Step 5: Configure the SSH Daemon
Edit /etc/ssh/sshd_config to enable challenge-response authentication, which is required for PAM-based two-factor prompts:
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
vi /etc/ssh/sshd_config
Find and set the following directives. If a directive is commented out, uncomment it and change the value:
ChallengeResponseAuthentication yes
UsePAM yes
To require both a password and an OTP code (the strongest configuration), add or modify the AuthenticationMethods directive:
AuthenticationMethods keyboard-interactive
If you also want to allow public key authentication to bypass OTP (common for automation accounts), use a comma-separated list:
AuthenticationMethods publickey,keyboard-interactive
This means a user must provide either a public key by itself, or both a password and an OTP code. For maximum security on interactive logins, keep only keyboard-interactive.
Also ensure that password authentication is enabled so that the keyboard-interactive flow can prompt for it:
PasswordAuthentication yes
Step 6: Restart the SSH Service
systemctl restart sshd
Verify the service is running without errors:
systemctl status sshd
Important: Do not close your current SSH session yet. Open a second terminal window and test the new configuration from there before disconnecting.
Step 7: Test Two-Factor Authentication
From a second terminal, SSH to the server as the user who ran google-authenticator:
ssh exampleuser@your-server-ip
You should see two sequential prompts:
Verification code:
Password:
Enter the current six-digit TOTP code from your authenticator app at the first prompt, then enter the account’s Linux password at the second. On success, you will be logged in.
If authentication fails, check the system authentication log for clues:
tail -50 /var/log/secure
Common issues include clock skew between the server and phone (ensure chronyd is running: systemctl status chronyd) and the ~/.google_authenticator file having incorrect permissions (it must be readable only by the owning user: chmod 600 ~/.google_authenticator).
Step 8: Handling Service Accounts and Automation
Automation scripts and monitoring agents that use SSH should authenticate exclusively with public key authentication and be excluded from OTP requirements. Create a Match block in /etc/ssh/sshd_config to override AuthenticationMethods for specific users or groups:
Match User deploybot
AuthenticationMethods publickey
Restart sshd after making this change:
systemctl restart sshd
Conclusion
Two-factor SSH authentication with Google Authenticator provides a substantial improvement in server access security with minimal operational overhead. The combination of the pam_google_authenticator.so PAM module and the SSH ChallengeResponseAuthentication setting intercepts every keyboard-interactive login and demands a valid TOTP code in addition to a password. For most RHEL 7 servers handling sensitive workloads, this configuration should be considered baseline rather than optional. Once deployed, keep a recovery plan in place — store emergency scratch codes offline and document the process for re-enrolling a lost device — and periodically verify that the authentication flow still works as expected after any PAM or SSH package updates.