How To Set Up SSH Two-Factor Authentication on AlmaLinux 10
SSH attacks increased by 147% in 2024, making robust authentication mechanisms absolutely critical for server security. With over 2.5 billion daily SSH login attempts recorded globally, implementing two-factor authentication (2FA) has become a necessity rather than an option for system administrators managing AlmaLinux servers.
Two-factor authentication adds an essential security layer by requiring users to provide both their password and a time-sensitive verification code generated by their mobile device. This dramatically reduces the risk of unauthorized access, even if passwords are compromised through data breaches or brute force attacks.
AlmaLinux 10 represents the latest evolution in enterprise-grade Linux distributions, offering enhanced security features, improved SELinux policies, and robust compatibility with Red Hat Enterprise Linux. Its stability and security-focused architecture make it an ideal platform for implementing advanced authentication mechanisms in production environments.
This comprehensive guide will walk you through the complete process of setting up SSH two-factor authentication on AlmaLinux 10, ensuring your server infrastructure maintains the highest security standards while remaining accessible to authorized users.
Prerequisites and System Requirements
System Requirements
Before implementing SSH 2FA on your AlmaLinux 10 system, ensure your server meets the following requirements:
- AlmaLinux 10 server with administrative access (root or sudo privileges)
- Minimum 2GB RAM for optimal performance during authentication processes
- 10GB available disk space for logs and configuration files
- Stable network connectivity for time synchronization and package downloads
- Active internet connection for initial setup and mobile app synchronization
Required Software and Tools
Successful SSH two-factor authentication implementation requires several key components:
Server-side requirements:
- OpenSSH server (openssh-server package) – verify installation with
rpm -qa | grep openssh
- Google Authenticator PAM module for generating and verifying TOTP codes
- QR code libraries for initial mobile device setup
- Text editor (nano, vim, or your preferred editor)
Client-side requirements:
- Mobile device (Android or iOS) with authenticator application
- Authenticator app such as Google Authenticator, Authy, Microsoft Authenticator, or FreeOTP
- Secondary device for backup access during emergency situations
Pre-configuration Security Considerations
Before proceeding with 2FA implementation, establish these critical security measures:
- Backup access method: Configure SSH key-based authentication before implementing 2FA. This provides an alternative access method if 2FA configuration issues arise.
- Console access: Ensure physical or out-of-band console access to your server. KVM, IPMI, or direct console access prevents complete lockout during configuration errors.
- Firewall configuration: Verify SSH service accessibility through your firewall. Default SSH port 22 should be accessible, or configure custom ports as needed.
- User account preparation: Test standard password authentication for all user accounts that will use 2FA before implementing additional security layers.
Understanding Two-Factor Authentication Methods
Types of 2FA for SSH
Multiple two-factor authentication methods exist for SSH implementation, each with distinct security characteristics:
Time-based One-Time Password (TOTP) represents the most widely adopted method. TOTP generates six-digit codes that refresh every 30 seconds, synchronized between your server and mobile device. This method offers excellent security without requiring internet connectivity after initial setup.
Universal 2nd Factor (U2F) hardware tokens provide the highest security level through physical authentication devices. YubiKey and similar hardware tokens generate cryptographic signatures but require additional software and user training.
SMS-based codes offer convenience but present significant security vulnerabilities. SIM swapping attacks and network interception make SMS-based 2FA unsuitable for production environments requiring robust security.
Google Authenticator PAM Module Overview
The Google Authenticator PAM (Pluggable Authentication Module) integrates seamlessly with AlmaLinux’s authentication infrastructure. PAM modules handle authentication requests from various services, including SSH, and can enforce multiple authentication factors.
When users attempt SSH connections, PAM processes their credentials through configured modules. The Google Authenticator module generates server-side secrets, creates QR codes for mobile app configuration, and validates TOTP codes during login attempts.
This architecture ensures TOTP validation occurs locally on your server, eliminating dependencies on external authentication services while maintaining high security standards.
Installing Google Authenticator on AlmaLinux 10
Enabling EPEL Repository
AlmaLinux 10 requires the Extra Packages for Enterprise Linux (EPEL) repository for Google Authenticator installation:
sudo dnf install epel-release -y
Verify EPEL repository installation:
sudo dnf repolist | grep epel
The output should display enabled EPEL repositories. Update your package cache to include newly available packages:
sudo dnf update -y
Installing Required Packages
Install Google Authenticator and supporting packages with a single command:
sudo dnf install google-authenticator qrencode-libs -y
This installation includes:
- google-authenticator: Core PAM module for TOTP authentication
- qrencode-libs: QR code generation libraries for mobile device setup
- libqrencode: Additional QR code dependencies
Verify successful installation by checking package status:
rpm -qa | grep google-authenticator
rpm -qa | grep qrencode
Post-Installation Verification
Confirm Google Authenticator PAM module availability:
ls -la /lib64/security/ | grep google
Expected output shows:
pam_google_authenticator.so
Check system logs for installation completion:
sudo journalctl -xe | grep google-authenticator
Test Google Authenticator command availability:
which google-authenticator
The command should return /usr/bin/google-authenticator
, confirming successful installation.
Configuring Google Authenticator
Running the Initial Setup
Execute Google Authenticator setup for your user account. Never run this as root – always configure 2FA for specific user accounts:
google-authenticator
The setup process presents several important questions:
Question 1: “Do you want authentication tokens to be time-based?”
Answer: y
(Yes)
Time-based tokens provide optimal security and mobile app compatibility.
Question 2: “Do you want me to update your “~/.google_authenticator” file?”
Answer: y
(Yes)
This creates the configuration file containing your secret key and backup codes.
QR Code Generation and Mobile App Setup
The setup displays a QR code for mobile device configuration. Several options exist for QR code scanning:
Option 1: Direct scanning
Use your mobile authenticator app to scan the displayed QR code directly from your terminal.
Option 2: Manual entry
If QR code display is unavailable, manually enter the secret key shown below the QR code into your authenticator app.
Option 3: Emergency backup codes
Record the emergency scratch codes displayed during setup. Store these codes securely offline for account recovery.
Popular authenticator apps:
- Google Authenticator (Android/iOS)
- Authy (Android/iOS) – includes cloud backup
- Microsoft Authenticator (Android/iOS)
- FreeOTP (Android/iOS) – open-source alternative
After adding your account to the mobile app, verify code generation by checking that six-digit codes refresh every 30 seconds.
Security Configuration Options
Complete the remaining setup questions for optimal security:
Question 3: “Do you want to disallow multiple uses of the same authentication token?”
Answer: y
(Yes)
This prevents replay attacks using intercepted codes.
Question 4: “By default, tokens are good for 30 seconds. Do you want to increase the time skew?”
Answer: n
(No)
Default 30-second windows provide adequate synchronization tolerance.
Question 5: “Do you want to enable rate-limiting for authentication attempts?”
Answer: y
(Yes)
Rate limiting prevents brute force attacks against TOTP codes by limiting authentication attempts to 3 every 30 seconds.
Your Google Authenticator configuration file is created at ~/.google_authenticator
with restricted permissions (600) for security.
Configuring SSH Daemon Settings
Modifying SSH Configuration File
SSH daemon configuration requires several modifications to enable 2FA authentication. Create a backup of your current SSH configuration:
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup
Edit the SSH configuration file:
sudo vim /etc/ssh/sshd_config
Add or modify these directives:
# Enable challenge-response authentication
ChallengeResponseAuthentication yes
# Enable PAM authentication
UsePAM yes
# Configure authentication methods
AuthenticationMethods publickey,keyboard-interactive
Important configuration notes:
The AuthenticationMethods
directive enforces both SSH key authentication and keyboard-interactive (2FA) authentication. Users must provide both SSH keys and TOTP codes.
For password + 2FA authentication (less secure), use:
AuthenticationMethods password,keyboard-interactive
Advanced SSH Configuration Options
Enhance security with additional SSH hardening options:
# Change default SSH port
Port 2222
# Disable root login
PermitRootLogin no
# Limit login attempts
MaxAuthTries 3
# Set connection timeouts
ClientAliveInterval 300
ClientAliveCountMax 2
# Disable password authentication (if using keys only)
PasswordAuthentication no
# Specify allowed users
AllowUsers username1 username2
# Enable strict mode
StrictModes yes
Protocol and cipher configuration:
# Force SSH protocol version 2
Protocol 2
# Specify secure ciphers
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
# Secure MAC algorithms
MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com
SSH Service Management
Validate SSH configuration syntax before applying changes:
sudo sshd -t
If no errors appear, restart SSH service:
sudo systemctl restart sshd
Enable SSH service for automatic startup:
sudo systemctl enable sshd
Monitor SSH service status:
sudo systemctl status sshd
Check SSH service logs for errors:
sudo journalctl -u sshd -f
Configuring PAM (Pluggable Authentication Module)
Understanding PAM Configuration
PAM manages authentication requests across Linux services through modular configuration files. Each service, including SSH, has its own PAM configuration defining authentication requirements.
AlmaLinux 10 uses the /etc/pam.d/
directory for PAM configurations. The SSH service configuration resides in /etc/pam.d/sshd
.
PAM modules process authentication in specific order:
- requisite: Authentication must succeed; failure terminates process
- required: Authentication must succeed; process continues regardless
- sufficient: Success completes authentication; failure continues
- optional: Results don’t affect overall authentication
Modifying SSH PAM Configuration
Create a backup of the current PAM SSH configuration:
sudo cp /etc/pam.d/sshd /etc/pam.d/sshd.backup
Edit the SSH PAM configuration:
sudo vim /etc/pam.d/sshd
Add the Google Authenticator module. Insert this line after the existing auth directives:
auth required pam_google_authenticator.so
For gradual deployment, use the nullok
parameter:
auth required pam_google_authenticator.so nullok
The nullok
parameter allows users without 2FA configuration to authenticate normally, enabling phased rollout.
Complete PAM configuration example:
#%PAM-1.0
auth required pam_sepermit.so
auth substack password-auth
auth required pam_google_authenticator.so nullok
account required pam_nologin.so
account include password-auth
password include password-auth
session required pam_selinux.so close
session required pam_loginuid.so
session required pam_selinux.so open env_params
session required pam_namespace.so
session optional pam_keyinit.so force revoke
session include password-auth
PAM Configuration Options and Security
Advanced Google Authenticator PAM options enhance security and usability:
Rate limiting configuration:
auth required pam_google_authenticator.so nullok secret=/var/lib/google-authenticator/${USER}
Grace period for time skew:
auth required pam_google_authenticator.so nullok grace_period=30
Enforce file permissions:
auth required pam_google_authenticator.so nullok try_first_pass
SELinux considerations:
AlmaLinux 10’s enhanced SELinux policies may require additional configuration. Check SELinux status:
sudo sestatus
If SELinux is enforcing, verify Google Authenticator contexts:
ls -Z ~/.google_authenticator
Set appropriate SELinux contexts if needed:
sudo restorecon -R /home/username/.google_authenticator
Testing and Verification
Initial Testing Process
Critical safety measure: Test 2FA authentication from a separate terminal session while maintaining your current administrative session. This prevents lockout if configuration errors occur.
Open a new terminal window and attempt SSH connection:
ssh username@your-server-ip
Expected authentication flow:
- SSH key authentication (if configured)
- Password prompt (if using password authentication)
- Verification code prompt: “Verification code:”
Enter the six-digit code from your mobile authenticator app. Successful authentication should grant access to your server.
Common authentication prompts:
Password:
– Enter your user account passwordVerification code:
– Enter current TOTP code from mobile app(current) UNIX password:
– Alternative password prompt
Comprehensive Testing Scenarios
Test multiple authentication scenarios to ensure complete functionality:
Test 1: Correct credentials
- Username: correct
- Password: correct
- TOTP code: correct
- Expected result: Successful login
Test 2: Incorrect TOTP code
- Username: correct
- Password: correct
- TOTP code: incorrect or expired
- Expected result: Authentication failure
Test 3: Emergency scratch codes
Use backup codes generated during initial setup:
- Username: correct
- Password: correct
- Verification code: emergency scratch code
- Expected result: Successful login (code becomes invalid)
Test 4: Multiple user accounts
Configure and test 2FA for additional user accounts to verify system-wide functionality.
Log Analysis and Monitoring
Monitor authentication events through system logs:
sudo tail -f /var/log/secure
Successful 2FA authentication log entry:
Jul 29 17:15:32 server sshd[12345]: Accepted keyboard-interactive/pam for username from 192.168.1.100 port 54321 ssh2
Failed 2FA authentication log entry:
Jul 29 17:16:15 server sshd[12346]: Failed keyboard-interactive/pam for username from 192.168.1.100 port 54322 ssh2
Set up log monitoring with logwatch or configure rsyslog for centralized logging:
sudo dnf install logwatch -y
sudo vim /etc/logwatch/conf/logwatch.conf
Configure log rotation for authentication logs:
sudo vim /etc/logrotate.d/sshd
Troubleshooting Common Issues
Authentication Failures
Time synchronization problems represent the most common 2FA issue. TOTP codes require accurate time synchronization between server and mobile device.
Check server time:
timedatectl status
Synchronize server time:
sudo chrony sources -v
sudo systemctl restart chronyd
Configure automatic time synchronization:
sudo timedatectl set-ntp true
Mobile device time synchronization:
- Android: Settings → Date & time → Automatic date & time
- iOS: Settings → General → Date & Time → Set Automatically
PAM configuration errors cause authentication failures:
Verify PAM syntax:
sudo pam-config --check
Test PAM authentication manually:
sudo pamtester sshd username authenticate
SSH configuration conflicts:
Validate SSH configuration:
sudo sshd -t -f /etc/ssh/sshd_config
Reset to default configuration if needed:
sudo cp /etc/ssh/sshd_config.backup /etc/ssh/sshd_config
sudo systemctl restart sshd
Connectivity and Access Issues
Complete lockout prevention:
Always maintain alternative access methods:
- Physical console access
- IPMI or out-of-band management
- Secondary SSH configuration on different port
Emergency access procedures:
Boot into single-user mode to disable 2FA temporarily:
- Restart server and interrupt boot process
- Add
single
to kernel parameters - Edit PAM configuration to comment out Google Authenticator module
- Restart SSH service
Network connectivity troubleshooting:
Test SSH connectivity:
ssh -v username@server-ip
Check firewall rules:
sudo firewall-cmd --list-all
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload
Verify SSH service binding:
sudo netstat -tlnp | grep :22
AlmaLinux 10 Specific Considerations
SELinux policy conflicts:
Check SELinux denials:
sudo ausearch -m AVC -ts recent
Generate custom SELinux policy if needed:
sudo audit2allow -a -M google-authenticator
sudo semodule -i google-authenticator.pp
Firewall configuration:
Configure firewalld for SSH access:
sudo firewall-cmd --permanent --add-port=22/tcp
sudo firewall-cmd --reload
Package dependency resolution:
Update package database:
sudo dnf clean all
sudo dnf update -y
Reinstall Google Authenticator if corruption occurs:
sudo dnf remove google-authenticator -y
sudo dnf install google-authenticator -y
Security Best Practices and Hardening
Additional Security Measures
SSH key-based authentication combined with 2FA provides maximum security. Generate ED25519 SSH keys for enhanced cryptographic security:
ssh-keygen -t ed25519 -b 4096 -f ~/.ssh/id_ed25519
Copy public keys to authorized servers:
ssh-copy-id -i ~/.ssh/id_ed25519.pub username@server-ip
Configure SSH to require both keys and 2FA:
AuthenticationMethods publickey,keyboard-interactive
IP address restrictions limit access to trusted networks:
# Allow SSH only from specific networks
AllowUsers username@192.168.1.0/24
AllowUsers username@10.0.0.0/8
Fail2ban integration prevents brute force attacks:
sudo dnf install fail2ban -y
sudo vim /etc/fail2ban/jail.local
Configure fail2ban for SSH protection:
[sshd]
enabled = true
port = ssh
logpath = /var/log/secure
maxretry = 3
bantime = 3600
Certificate-based authentication provides enterprise-grade security for large environments.
Ongoing Security Maintenance
Regular security updates:
Configure automatic security updates:
sudo dnf install dnf-automatic -y
sudo vim /etc/dnf/automatic.conf
Set update schedule:
sudo systemctl enable --now dnf-automatic.timer
Backup code management:
Regenerate emergency codes periodically:
google-authenticator --force
Store backup codes in secure, offline locations such as encrypted password managers or physical security storage.
User training programs:
Develop security awareness training covering:
- Mobile device security practices
- TOTP code protection
- Emergency access procedures
- Social engineering awareness
Security audit procedures:
Implement regular security audits:
sudo lynis audit system
Monitor authentication logs with automated tools:
sudo logwatch --detail High --service sshd --print
Enterprise Security Integration
Centralized authentication systems:
Integrate with LDAP or Active Directory:
sudo dnf install sssd realmd -y
sudo realm join domain.example.com
Compliance frameworks:
Configure FIPS 140-2 compliance:
sudo fips-mode-setup --enable
Implement SOC 2 controls through comprehensive logging and monitoring.
Scalability planning:
Deploy configuration management tools:
- Ansible playbooks for automated 2FA deployment
- Puppet modules for configuration management
- SaltStack for large-scale orchestration
Disaster recovery considerations:
Document recovery procedures:
- Emergency access methods
- Configuration backup locations
- User account recovery processes
- Mobile device replacement procedures
Advanced Configuration Options
Multi-User Environment Setup
Automated deployment scripts streamline 2FA rollout across multiple users:
#!/bin/bash
# 2FA deployment script
USERS=("user1" "user2" "user3")
for user in "${USERS[@]}"; do
sudo -u $user google-authenticator --time-based --disallow-reuse --force --rate-limit=3 --rate-time=30 --window-size=3
echo "2FA configured for $user"
done
Centralized configuration management:
Store Google Authenticator configurations in centralized location:
sudo mkdir -p /etc/google-authenticator
sudo vim /etc/pam.d/sshd
Modify PAM configuration for centralized secrets:
auth required pam_google_authenticator.so secret=/etc/google-authenticator/${USER}
Group-based 2FA policies:
Implement 2FA requirements by user groups:
# Create 2FA required group
sudo groupadd 2fa-required
sudo usermod -a -G 2fa-required username
# Configure conditional PAM authentication
auth [success=1 default=ignore] pam_succeed_if.so quiet_success user ingroup 2fa-required
auth required pam_google_authenticator.so
Integration with Other Security Tools
SIEM integration enhances security monitoring:
Configure rsyslog forwarding:
sudo vim /etc/rsyslog.conf
Add SIEM forwarding rule:
*.* @@siem-server:514
Intrusion detection coordination:
Install and configure AIDE:
sudo dnf install aide -y
sudo aide --init
sudo mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz
Schedule regular integrity checks:
sudo crontab -e
0 2 * * * /usr/sbin/aide --check
Performance optimization:
Monitor authentication performance:
sudo systemd-analyze blame | grep sshd
Optimize PAM module loading:
sudo vim /etc/security/pam_env.conf
Backup and disaster recovery:
Automate configuration backups:
#!/bin/bash
# Backup 2FA configurations
tar -czf /backup/2fa-config-$(date +%Y%m%d).tar.gz \
/etc/ssh/sshd_config \
/etc/pam.d/sshd \
/home/*/.google_authenticator
Congratulations! You have successfully set up SSH two-factor authentication. Thanks for using this tutorial to setting up SSH two-factor authentication on AlmaLinux OS 10 system. For additional or useful information, we recommend you check the official AlmaLinux website.