Skip to main content

Command Palette

Search for a command to run...

How To Enable MFA For Sudo and SSH Access

Updated
5 min read
How To Enable MFA For Sudo and SSH Access

Multi-Factor Authentication (MFA) adds a critical security layer to your Linux servers by requiring users to prove their identity through something they know (SSH key or password) and something they have (a time-based one-time password from their phone). This guide walks you through configuring MFA for both SSH login and sudo command execution using Google Authenticator.

Prerequisites

Before configuring MFA, install the required package:

Debian/Ubuntu:

sudo apt update
sudo apt install libpam-google-authenticator

RHEL/CentOS/Rocky:

sudo dnf install google-authenticator

Configuration Files Overview

Enabling MFA requires modifying these key areas:

FilePurpose
/etc/pam.d/sshdControls SSH authentication via PAM
/etc/pam.d/sudoControls sudo authentication via PAM
/etc/ssh/sshd_configEnables challenge-response for SSH
/etc/sudoers or /etc/sudoers.d/*Controls whether sudo prompts for authentication
~/.google_authenticatorStores per-user TOTP secrets

Step 1: Configure SSH Daemon

Edit /etc/ssh/sshd_config to enable keyboard-interactive authentication:

# Enable challenge-response authentication
ChallengeResponseAuthentication yes

# Required on Debian 12+ / Ubuntu 22.04+
KbdInteractiveAuthentication yes

# Disable password-only authentication
PasswordAuthentication no

# Require both SSH key and TOTP for users
AuthenticationMethods publickey,keyboard-interactive

Per-user configuration (optional):

If you have service accounts that should bypass MFA:

# Default: require MFA
AuthenticationMethods publickey,keyboard-interactive

# Exception for automation accounts
Match User ansible,deploy
    AuthenticationMethods publickey

Restart SSH after changes:

sudo systemctl restart sshd

Step 2: Configure PAM for SSH

Edit /etc/pam.d/sshd to enforce Google Authenticator:

# /etc/pam.d/sshd

# MFA enforcement - add at the top of auth section
auth required pam_google_authenticator.so nullok

# Comment out or remove standard password auth if using keys + TOTP only
#@include common-auth

# Keep the rest of the file unchanged
account    required     pam_nologin.so
@include common-account
@include common-session
@include common-password

Key directives:

DirectiveMeaning
auth requiredAuthentication fails if this module fails
pam_google_authenticator.soThe TOTP verification module
nullokAllows users without MFA configured to still log in (remove once all users are enrolled)

Step 3: Configure PAM for Sudo

Edit /etc/pam.d/sudo to require TOTP for privilege escalation:

# /etc/pam.d/sudo

# Session configuration
session    required   pam_limits.so
session    required   pam_env.so readenv=1 user_readenv=0
session    required   pam_env.so readenv=1 envfile=/etc/default/locale user_readenv=0

# MFA enforcement
auth required pam_google_authenticator.so
auth required pam_permit.so

# Disable password-based sudo
#@include common-auth

@include common-account
@include common-session-noninteractive

This configuration ensures every sudo command requires a fresh TOTP code.

Step 4: Configure Sudoers for MFA

For sudo MFA to work, users must not have NOPASSWD in their sudoers configuration. The NOPASSWD directive bypasses PAM authentication entirely, skipping the MFA prompt.

Check existing sudoers configurations:

sudo cat /etc/sudoers
sudo ls -la /etc/sudoers.d/
sudo cat /etc/sudoers.d/*

For users who need MFA, use visudo to ensure they have:

# Requires authentication (triggers PAM/MFA)
username ALL=(ALL) ALL

For automation accounts that should bypass MFA, use NOPASSWD:

# No authentication prompt (bypasses PAM/MFA)
ansible ALL=(ALL) NOPASSWD: ALL

Editing sudoers safely:

Always use visudo to edit sudoers files - it validates syntax before saving:

# Edit main sudoers file
sudo visudo

# Edit user-specific file in sudoers.d
sudo visudo -f /etc/sudoers.d/uche

Example configurations:

User TypeSudoers EntryMFA Behavior
Regular useruche ALL=(ALL) ALLPrompted for TOTP
Admin useradmin ALL=(ALL) ALLPrompted for TOTP
Automationansible ALL=(ALL) NOPASSWD: ALLNo prompt, bypasses MFA
Deploy servicedeploy ALL=(ALL) NOPASSWD: /usr/bin/systemctlNo prompt for specific commands

Common mistake:

If you see this in your sudoers and want MFA for that user:

# WRONG - bypasses MFA
uche ALL=(ALL) NOPASSWD: ALL

Change it to:

# CORRECT - triggers MFA
uche ALL=(ALL) ALL

Dev vs Production Considerations

Consider different MFA policies based on environment:

EnvironmentRecommended Policy
ProductionMFA strictly enforced for all users
StagingMFA enforced, mirrors production
DevelopmentMFA optional or relaxed for faster iteration

Implementation approach:

For development servers, you might use conditional PAM configuration:

# /etc/pam.d/sshd (Development)

# Relaxed: standard authentication without MFA
@include common-auth

# Production would instead have:
# auth required pam_google_authenticator.so

Trade-offs:

Strict MFA EverywhereRelaxed MFA in Dev
Consistent security postureFaster development workflow
No environment-specific configsRisk of bad habits carrying to production
Simpler auditingDevelopers may resist MFA adoption

A common middle ground: enforce MFA for sudo everywhere, but relax SSH MFA in dev environments.

Why MFA for SSH and Sudo Matters

The Risk Landscape

Traditional single-factor authentication leaves gaps:

Attack VectorSingle-Factor RiskMFA Mitigation
Stolen SSH keyFull server accessAttacker lacks TOTP device
Compromised passwordFull server accessPassword alone insufficient
Insider threatDifficult to prove unauthorized accessPhysical device required
Lateral movementAttacker escalates via sudoEach sudo requires fresh TOTP

Defense in Depth

MFA creates multiple barriers:

Attacker must compromise:

  SSH Key ──────────┐
                    ├──▶ SSH Access ──┐
  TOTP Device ──────┘                 
                                      
                    ┌─────────────────┘
                    
                    
  TOTP Device ──────────▶ Sudo Access ──▶ Privileged Commands

Even with a compromised SSH key, the attacker cannot:

  • Log in without the TOTP code

  • Execute privileged commands without continuous TOTP verification

Compliance Benefits

MFA for privileged access helps meet:

  • PCI-DSS: Requirement 8.3 — MFA for administrative access

  • SOC 2: Logical access controls

  • HIPAA: Access control safeguards

  • NIST 800-53: IA-2 Multi-factor authentication

Wrap up

Enabling MFA for SSH and sudo creates a robust security posture:

  • SSH access requires: valid SSH key + valid TOTP code

  • Privilege escalation requires: valid TOTP code per command

The implementation centers on:

  1. Installing libpam-google-authenticator

  2. Configuring /etc/ssh/sshd_config for challenge-response

  3. Modifying /etc/pam.d/sshd for SSH MFA

  4. Modifying /etc/pam.d/sudo for sudo MFA

  5. Removing NOPASSWD from sudoers for users requiring MFA

This approach ensures that even sophisticated attacks face multiple barriers before achieving privileged access to your systems.