
Table of Contents
By Khimananda Oli | Last reviewed: August 2026
Default SSH configurations are a primary attack vector for any internet-facing infrastructure, exposing systems to relentless credential stuffing and brute-force bots. To properly harden SSH on Linux servers, you must move beyond default settings and implement a defense-in-depth strategy that combines cryptographic key authentication, network-layer filtering, and automated intrusion prevention. This guide provides the exact configuration steps I use to secure production environments against modern threats.
/etc/ssh/sshd_config, enforce Ed25519 key-based access, restrict traffic via UFW or nftables, and deploy fail2ban to automatically block IPs exhibiting malicious behavior. Always validate configuration syntax before restarting the daemon to prevent lockouts.How do you configure SSH key authentication and disable passwords?
Password authentication is the single biggest risk factor when you harden SSH on Linux servers. Human-chosen passwords are predictable, reused, and trivially cracked by modern GPU-accelerated tools. Key-based authentication replaces this weak link with cryptographic proof of identity. For new deployments in 2026, Ed25519 keys are the standard; they offer better security than RSA at a fraction of the size and are supported by all current OpenSSH versions.
Generate strong Ed25519 keys
Create your key pair locally. Never generate keys on the server itself. The comment field should identify the key's purpose and owner for audit trails.
ssh-keygen -t ed25519 -C "admin@khimananda-prod-2026" -f ~/.ssh/id_ed25519_prod Deploy keys securely
Copy the public key to the server. If password auth is still enabled temporarily, use ssh-copy-id. For hardened systems where passwords are already disabled, append the key manually via console or out-of-band management.
# From your local machine
ssh-copy-id -i ~/.ssh/id_ed25519_prod.pub user@server-ip
# Verify permissions on the server (critical)
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R $USER:$USER ~/.ssh Harden sshd_config for key-only access
Edit /etc/ssh/sshd_config. These directives form the baseline for any secure configuration. As detailed in the Ubuntu security hardening guide, always test configuration changes before applying them to avoid locking yourself out.
# /etc/ssh/sshd_config - Authentication Hardening
PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
ChallengeResponseAuthentication no
KbdInteractiveAuthentication no
UsePAM yes
# Disable root login entirely
PermitRootLogin no
# Restrict to specific users (optional but recommended)
AllowUsers deployer admin
# Protocol 2 is default in modern OpenSSH, but explicit is safer
Protocol 2 Validate the configuration syntax before reloading. A typo here can make the server unreachable.
sudo sshd -t && sudo systemctl reload sshd What network-level controls protect SSH from brute-force attacks?
Even with perfect authentication, exposing SSH to the entire internet invites noise. Network-level controls reduce your attack surface and filter out opportunistic scanners before they consume daemon resources. This is especially relevant for teams managing infrastructure in Nepal or other regions where VPS providers may not offer advanced cloud-native firewalls; host-level filtering becomes your primary perimeter.
Configure UFW to restrict SSH access
If you use Ubuntu, UFW provides a clean interface over nftables. Allow SSH only from trusted CIDR ranges. If you must allow broader access, combine this with fail2ban.
# Allow SSH from office IP range only
sudo ufw allow from 203.0.113.0/24 to any port 22 proto tcp comment "Office SSH"
# Default deny incoming
sudo ufw default deny incoming
sudo ufw enable Change the default port (security through obscurity)
Changing port 22 does not stop targeted attacks, but it dramatically reduces log noise from automated botnets. This makes genuine alerts easier to spot. Update both sshd_config and your firewall rules simultaneously.
# In /etc/ssh/sshd_config
Port 2222
# Update UFW accordingly
sudo ufw allow 2222/tcp comment "SSH Custom Port" Implement TCP wrappers as a secondary filter
For legacy compatibility or additional layering, /etc/hosts.allow and /etc/hosts.deny provide application-level filtering independent of the kernel firewall.
# /etc/hosts.deny
sshd: ALL
# /etc/hosts.allow
sshd: 203.0.113.0/24 198.51.100.50 How does fail2ban automate intrusion prevention for SSH?
Network filters handle known-good sources, but you cannot whitelist the entire internet. Fail2ban bridges this gap by watching authentication logs and temporarily banning IPs that exceed failure thresholds. This turns passive logging into active defense. When combined with the fail2ban configuration guide, you get a production-ready setup that survives reboots and integrates with your existing firewall.
Install and configure fail2ban
Never edit jail.conf directly; package updates will overwrite it. Create jail.local instead.
sudo apt install fail2ban
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local Define SSH jail parameters
Tune these values based on your traffic patterns. Aggressive settings catch more attackers but risk false positives for legitimate users with flaky connections.
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
banaction = ufw
[sshd]
enabled = true
port = 2222
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 24h Verify and manage bans
Monitor fail2ban status regularly. False positives happen; ensure you have an unban procedure documented for your team.
# Check jail status
sudo fail2ban-client status sshd
# Manually unban a legitimate user
sudo fail2ban-client set sshd unbanip 203.0.113.50
# Test regex patterns without banning
sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf Which SSH hardening methods actually improve security?
Not every hardening recommendation delivers real value. Some are outdated, others are cosmetic. Understanding the difference prevents wasted effort and false confidence. The table below separates genuine security improvements from common misconceptions based on current threat models and OpenSSH 9.x behavior.
| Hardening Measure | Security Impact | Operational Cost | Recommendation |
|---|---|---|---|
| Disable Password Auth | Critical — eliminates credential stuffing | Low — requires key distribution | Mandatory for all production |
| Ed25519 Keys | High — stronger crypto, smaller keys | None — drop-in replacement | Default for new deployments |
| Non-Standard Port | Low — stops dumb bots only | Medium — breaks tooling assumptions | Optional — reduces log noise |
| Fail2Ban | High — automated active defense | Low — set-and-forget after tuning | Recommended for public-facing |
| Disable Root Login | Critical — enforces accountability | Low — use sudo instead | Mandatory everywhere |
| SSH Certificates (CA) | Very High — scalable key management | High — requires CA infrastructure | Fleets >20 servers or compliance |
| Two-Factor (TOTP) | High — defense against key theft | Medium — adds login friction | Privileged access only |
For teams managing database servers alongside application infrastructure, apply the same principles consistently. The PostgreSQL administration essentials guide covers securing database connections with similar rigor, ensuring your entire stack follows the same authentication standards.
How do you maintain SSH security posture over time?
Hardening is not a one-time event. Configuration drift, package updates, and new vulnerabilities erode security over time. Sustainable hardening requires automation and observability. Treat your SSH configuration as code: version it, review it, and deploy it through your configuration management system rather than manual edits.
- Automate deployment: Use Ansible, Terraform, or cloud-init to push
sshd_configand fail2ban rules. Manual edits on individual servers inevitably diverge. The initial Ubuntu server setup guide demonstrates integrating SSH hardening into provisioning workflows. - Monitor authentication events: Forward
/var/log/auth.logto your centralized logging stack. Alert on unusual patterns: successful logins from new geolocations, spikes in failures from internal IPs, or key additions outside change windows. - Audit authorized_keys regularly: Stale keys from departed employees or decommissioned services are a persistent risk. Implement quarterly reviews or automate key lifecycle management with SSH certificates.
- Test your backups: Before any hardening change, verify console access works. Cloud provider consoles, IPMI, or out-of-band management are your recovery path when SSH misconfiguration locks you out.
- Stay current: Subscribe to OpenSSH release announcements. New features like FIDO2 resident keys and improved algorithms arrive regularly; outdated versions miss critical protections.
Securing Remote Access for Production Workloads
To effectively harden SSH on Linux servers, combine Ed25519 key authentication, strict daemon configuration, network-layer filtering, and automated intrusion prevention into a cohesive defense strategy. Each layer compensates for the others' limitations: keys prevent credential theft, firewalls reduce exposure, fail2ban handles dynamic threats, and monitoring catches what slips through. Document your configuration, automate its deployment, and treat SSH security as an ongoing operational discipline rather than a checklist item. If your team needs help implementing these controls across a fleet or preparing for a compliance audit, reach out to discuss your infrastructure security requirements.