When implementing two-factor authentication for SSH on Ubuntu 14.04, we need to reconcile three authentication mechanisms:
1. Public key authentication (passwordless)
2. Google Authenticator TOTP codes
3. PAM module processing
The main configuration files requiring modification are:
/etc/ssh/sshd_config
/etc/pam.d/ssh
~/.google_authenticator (per-user)
Your current /etc/ssh/sshd_config
settings are mostly correct but need refinement:
# Enable challenge-response
ChallengeResponseAuthentication yes
# Specify authentication methods order
AuthenticationMethods publickey,keyboard-interactive
# PAM integration
UsePAM yes
# Additional recommended settings
PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
The PAM configuration in /etc/pam.d/ssh
requires careful ordering:
# Standard Unix auth
@include common-auth
# Google Authenticator (placed after standard auth)
auth required pam_google_authenticator.so nullok
# Additional security layers (optional)
auth required pam_deny.so
auth required pam_permit.so
If you're still getting password prompts, verify these potential solutions:
# Check PAM debugging (add to sshd_config)
LogLevel DEBUG3
# Verify module loading
ls -la /lib/security/pam_google_authenticator.so
# Test PAM stack
pamtester ssh user authenticate
Here's a verified working configuration for reference:
# /etc/ssh/sshd_config
Port 22
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
UsePrivilegeSeparation yes
KeyRegenerationInterval 3600
ServerKeyBits 1024
SyslogFacility AUTH
LogLevel INFO
LoginGraceTime 120
PermitRootLogin prohibit-password
StrictModes yes
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
IgnoreRhosts yes
RhostsRSAAuthentication no
HostbasedAuthentication no
PermitEmptyPasswords no
ChallengeResponseAuthentication yes
UsePAM yes
X11Forwarding yes
X11DisplayOffset 10
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server
AuthenticationMethods publickey,keyboard-interactive
# /etc/pam.d/ssh
# Standard Un*x authentication.
@include common-auth
# Google Authenticator
auth required pam_google_authenticator.so nullok
# Ensure users can still login if they haven't setup Google Auth
auth required pam_permit.so
Follow these steps for reliable implementation:
- Install libpam-google-authenticator package
- Run google-authenticator for each user
- Backup the generated secret and recovery codes
- Configure sshd_config as shown above
- Adjust PAM configuration carefully
- Test with ssh -v before restarting sshd
- Maintain backup SSH access during configuration
For enterprise environments, consider these enhancements:
# Rate limiting protection
auth required pam_google_authenticator.so nullok ratetime=30 window_size=3
# IP-based exclusions (for trusted networks)
Match Address 192.168.1.0/24
AuthenticationMethods publickey
When setting up two-factor authentication for SSH on Ubuntu 14.04, many administrators want to combine the security of public key authentication with the convenience of Google Authenticator. The ideal setup should:
- Require valid SSH public key
- Prompt for Google Authenticator code
- Not ask for password authentication
Here are the essential files that need modification:
/etc/ssh/sshd_config
# Enable challenge-response authentication
ChallengeResponseAuthentication yes
# Specify authentication methods (public key first, then Google Auth)
AuthenticationMethods publickey,keyboard-interactive
# Ensure PAM is enabled
UsePAM yes
# Optional: Disable password authentication completely
PasswordAuthentication no
/etc/pam.d/ssh
# Standard PAM configuration
@include common-auth
@include common-account
@include common-session
@include common-password
# Add Google Authenticator at the end
auth required pam_google_authenticator.so nullok
1. Order Matters in PAM Configuration
The position of the Google Authenticator line in /etc/pam.d/ssh is critical. It should appear after the standard PAM includes but before any final rules.
2. The nullok Parameter
While developing your setup, keep the nullok
parameter to allow users without 2FA configured to still log in. Remove it in production when all users have set up their authenticator.
3. Testing Configuration
Always test with a second terminal session open before logging out:
ssh -v -o PreferredAuthentications=publickey user@yourserver
Here's a complete walkthrough for a user named "devuser":
Step 1: Install Required Packages
sudo apt-get update
sudo apt-get install libpam-google-authenticator
Step 2: Configure Google Authenticator
su - devuser
google-authenticator
# Answer the configuration questions:
# - Time-based tokens: y
# - Update .google_authenticator: y
# - Disallow multiple uses: y
# - Increase window: n
# - Enable rate-limiting: y
Step 3: Final SSH Configuration
After testing, your final /etc/ssh/sshd_config should contain:
PubkeyAuthentication yes
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive
UsePAM yes
PasswordAuthentication no
If you're still seeing password prompts:
- Check PAM module order in /etc/pam.d/ssh
- Verify the user's ~/.ssh/authorized_keys permissions (should be 600)
- Ensure SELinux/AppArmor isn't blocking the PAM module
- Check auth.log for detailed errors:
tail -f /var/log/auth.log
For more granular control, you can modify the ~/.ssh/authorized_keys file:
command="/usr/sbin/login_duo",no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-rsa AAAAB3NzaC1yc2E...
This approach requires additional scripting but provides more flexibility.