Home/Engineer/Security Hardening/Hardening SSH: Locking Down …
Security HardeningIntermediateubuntudebiancentossshsshd_configSecurity

Hardening SSH: Locking Down sshd_config with Key-Only Login, AllowGroups, and MFA

Covers sshd_config hardening, switching to key-based authentication, and controlling SSH access with AllowGroups, Match blocks, and MFA. Automatic brute-force blocking with fail2ban is covered in a separate guide.

Contents
  1. The Starting Point for SSH Security — Audit Your Current Settings
  2. Core Hardening for /etc/ssh/sshd_config
  3. Setting Up SSH Key-Based Authentication
  4. Advanced Access Control — AllowGroups and Match Blocks
  5. Multi-Factor Authentication (MFA) — Key + TOTP
  6. Expose Only the SSH Port with UFW

The Starting Point for SSH Security — Audit Your Current Settings

SSH server defaults favor convenience, which leaves a wide attack surface. Before you change anything, check the values that are actually in effect.

Bash
sudo sshd -T | grep -Ei "permitrootlogin|passwordauthentication|^port|maxauthtries|allowusers|allowgroups"

This guide focuses on sshd_config hardening and access control. For automatic brute-force blocking and IP bans, apply the Blocking SSH Brute-Force Attacks with fail2ban guide as well.


Core Hardening for /etc/ssh/sshd_config

Bash
# Change the port (default 22 → custom port, reduces automated scan noise)
Port 2222

# Block direct root login
PermitRootLogin no

# Disable password authentication (apply after key setup is complete)
PasswordAuthentication no
KbdInteractiveAuthentication no   # Older versions: ChallengeResponseAuthentication no

# Disallow empty passwords
PermitEmptyPasswords no

# Auth attempt limit / login grace time
MaxAuthTries 3
LoginGraceTime 20

# Auto-close idle sessions (disconnect after 5 minutes of no response)
ClientAliveInterval 300
ClientAliveCountMax 0

# Disable unnecessary features
X11Forwarding no
AllowAgentForwarding no
AllowTcpForwarding no

Before applying, always validate the syntax then reload — this prevents lockouts caused by a bad config.

Bash
sudo sshd -t && sudo systemctl reload ssh   # Debian/Ubuntu: ssh, RHEL family: sshd

Prevent lockouts: Keep one extra SSH session open while you change settings. Do not close the existing session until you have confirmed access with a new session.


Setting Up SSH Key-Based Authentication

On the client (your PC) — Ed25519 keys are recommended (short, fast, and secure).

Bash
ssh-keygen -t ed25519 -C "deploy@myserver" -f ~/.ssh/myserver_ed25519
cat ~/.ssh/myserver_ed25519.pub

On the server — register the public key only (never copy the private key to the server).

Bash
mkdir -p ~/.ssh && chmod 700 ~/.ssh
echo "ssh-ed25519 AAAA... deploy@myserver" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

ssh-copy-id can do the above in a single command.

Bash
ssh-copy-id -i ~/.ssh/myserver_ed25519.pub -p 2222 deploy@server-ip
ssh -i ~/.ssh/myserver_ed25519 -p 2222 deploy@server-ip   # Verify key-based login

Apply PasswordAuthentication no in sshd_config only after you have confirmed key-based login works.


Advanced Access Control — AllowGroups and Match Blocks

Managing access by group is simpler than listing every user in AllowUsers.

Bash
# Create an SSH-allowed group and add users to it
sudo groupadd sshusers
sudo usermod -aG sshusers deploy
Bash
# sshd_config
AllowGroups sshusers

Match blocks let you apply per-condition policies. For example, key-only authentication for a deploy account, or allowing connections only from a specific network range.

Bash
# SFTP-only with chroot for a specific user
Match User backup
    ForceCommand internal-sftp
    ChrootDirectory /srv/backup
    AllowTcpForwarding no

# Allow password authentication only from the internal network (exception policy)
Match Address 10.0.0.0/8
    PasswordAuthentication yes

Multi-Factor Authentication (MFA) — Key + TOTP

To add another layer if a key is leaked, add TOTP (Google Authenticator, etc.).

Bash
sudo apt install libpam-google-authenticator
google-authenticator   # Interactive: scan the QR code, then save the emergency codes
Bash
# Add at the top of /etc/pam.d/sshd
auth required pam_google_authenticator.so

# /etc/ssh/sshd_config
KbdInteractiveAuthentication yes
AuthenticationMethods publickey,keyboard-interactive

Login now requires both the key and the OTP.


Expose Only the SSH Port with UFW

Bash
sudo ufw allow 2222/tcp
sudo ufw enable
sudo ufw status verbose

Next steps: For automatic blocking, see Blocking SSH Brute-Force Attacks with fail2ban. For a full initial check of a new server, see New Linux Server Initial Security Setup Checklist.

#ssh#sshd_config#Security#mfa
Editorial note

AI tools may assist drafting. Check the evidence in each guide for whether commands were run and which environment was used. Confirm the current docs for your version before applying instructions, and email us about errors. email us

Topic-related official docs (auto-linked · not per-claim sources)Linux man pages ↗OWASP documentation ↗

Questions & answers

Ask a question about this guide. We'll review and reply.