Many administrators face confusion when trying to configure SSH to support PAM-based two-factor authentication (like Google Authenticator) while simultaneously disabling traditional password authentication. The standard approach of setting all three parameters:
ChallengeResponseAuthentication no
PasswordAuthentication no
UsePAM no
completely disables PAM functionality, making 2FA impossible. Here's the proper configuration that solves this dilemma:
For Debian Jessie (and most modern Linux distributions), use these settings in /etc/ssh/sshd_config
:
# Disable password authentication
PasswordAuthentication no
# Enable PAM for 2FA
UsePAM yes
ChallengeResponseAuthentication yes
# Optional but recommended for 2FA setups
AuthenticationMethods publickey,keyboard-interactive
The real magic happens in the PAM configuration. Create or modify /etc/pam.d/sshd
:
# Standard Unix authentication (disabled for passwords)
auth requisite pam_unix.so nullok_secure noaudit nodelay
# Google Authenticator module
auth required pam_google_authenticator.so
# Common session setup
@include common-auth
@include common-account
@include common-session
@include common-password
PasswordAuthentication no: This prevents SSH from offering password authentication directly through the SSH protocol.
ChallengeResponseAuthentication yes: Enables PAM's challenge-response mechanism, which is required for 2FA implementations.
AuthenticationMethods: Specifies the allowed authentication methods in order. The keyboard-interactive
method is what PAM uses for challenge-response.
After making these changes, always test with:
sshd -t && systemctl restart sshd
Key troubleshooting commands:
# Check auth logs
tail -f /var/log/auth.log
# Verbose SSH client output
ssh -vvv user@host
For a complete Google Authenticator setup:
# Install the PAM module
apt-get install libpam-google-authenticator
# Configure for a user
sudo -u username google-authenticator
The configuration will generate a QR code for mobile app setup and emergency scratch codes.
1. Always maintain alternative access (like console access) when changing SSH configurations
2. Consider keeping public key authentication as a fallback method
3. Monitor failed authentication attempts in your logs
4. Regularly update your PAM modules and SSH server
When configuring SSH servers for security, many administrators face this dilemma: how to maintain PAM (Pluggable Authentication Modules) functionality while disabling traditional password authentication. This becomes particularly important when implementing Google Authenticator or other OTP solutions.
# Incorrect configuration that completely disables PAM
ChallengeResponseAuthentication no
PasswordAuthentication no
UsePAM no
Here's the proper configuration for /etc/ssh/sshd_config
:
# Enable PAM for modules like Google Authenticator
UsePAM yes
# Disable direct password authentication
PasswordAuthentication no
# Enable challenge-response (required for PAM)
ChallengeResponseAuthentication yes
Now we need to modify the PAM configuration to prevent password fallback. Edit /etc/pam.d/sshd
:
# Standard PAM modules
auth required pam_google_authenticator.so
auth required pam_deny.so # Explicitly deny other methods
auth required pam_permit.so
# Comment out or remove pam_unix.so line
# auth [success=1 default=ignore] pam_unix.so nullok_secure
After restarting SSH (systemctl restart sshd
), verify with:
ssh -v user@server
You should see debug output indicating publickey and keyboard-interactive methods, but no password prompt. If configured correctly, attempts to use passwords will fail while OTP works.
If authentication fails:
- Check
/var/log/auth.log
for PAM errors - Verify SELinux/AppArmor isn't blocking PAM modules
- Ensure the Google Authenticator config file exists (~/.google_authenticator)
- Confirm system time is synchronized (OTP is time-based)
For enhanced security, consider adding these to sshd_config
:
# Only allow specific authentication methods
AuthenticationMethods publickey,keyboard-interactive
# Require both public key AND OTP
Match User restricted_users
AuthenticationMethods publickey keyboard-interactive:publickey