
Table of Contents
By Khimananda Oli | Last reviewed: August 2026
Leaving default SSH configurations on internet-facing servers is an invitation for compromise, as automated bots scan public IP ranges continuously looking for weak credentials. To properly harden SSH: key auth, Fail2ban, and port hardening form the essential defense triad that stops the vast majority of unauthorized access attempts before they gain a foothold. This guide provides the exact configuration steps I use when performing an initial Ubuntu server setup to ensure production environments remain audit-ready and resilient against brute-force campaigns.
sshd_config, configure Fail2ban to ban IPs after failed attempts, and move SSH to a non-standard port to reduce automated scanner noise while maintaining strict key-only access control.How do you configure SSH key authentication and disable passwords?
Password authentication is the single largest attack surface on any SSH daemon. Even complex passwords can fall to credential stuffing or phishing, whereas cryptographic keys provide mathematical proof of identity that cannot be guessed. When I help teams transition from legacy setups, enforcing key-based auth is always step one in any AWS EC2 security baseline.
Generate and deploy Ed25519 keys
Ed25519 keys are smaller, faster, and more resistant to side-channel attacks than RSA. Generate a key pair on your local machine:
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/id_ed25519_prod Copy the public key to your server using ssh-copy-id while password auth is still temporarily enabled:
ssh-copy-id -i ~/.ssh/id_ed25519_prod.pub user@server-ip Harden sshd_config for key-only access
Edit the SSH daemon configuration file. Always validate syntax before restarting to avoid locking yourself out:
sudo nano /etc/ssh/sshd_config
# Critical hardening directives
PermitRootLogin no
PasswordAuthentication no
ChallengeResponseAuthentication no
PubkeyAuthentication yes
AuthenticationMethods publickey
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
AllowUsers deployer admin
X11Forwarding no
PermitEmptyPasswords no Validate and apply the configuration safely:
sudo sshd -t && sudo systemctl reload sshd The AllowUsers directive acts as an explicit whitelist. Even if an attacker obtains valid credentials for another system account, they cannot authenticate via SSH unless listed. This principle of least privilege aligns with ISO 27001 access control requirements and simplifies audit evidence collection.
How do you set up Fail2ban to prevent SSH brute-force attacks?
Fail2ban monitors authentication logs and dynamically updates firewall rules to block offending IP addresses. While key authentication prevents successful breaches, Fail2ban reduces log noise and resource exhaustion from persistent scanners. In my experience managing SOC 2 compliant infrastructure, this tool is essential for demonstrating active intrusion prevention controls.
Install and configure jail.local
Never edit jail.conf directly; package updates will overwrite it. Create a local override:
sudo apt install fail2ban -y
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local Configure the SSH jail with aggressive but practical thresholds:
[sshd]
enabled = true
port = 2222
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
findtime = 600
bantime = 3600
banaction = nftables-multiport Note that the port value must match your actual SSH port. If you changed SSH to 2222, Fail2ban must monitor that same port or it will watch the wrong service entirely. The nftables-multiport action is preferred over iptables on modern Ubuntu and Debian releases for better performance and compatibility.
Verify Fail2ban is actively protecting SSH
Check jail status and currently banned IPs:
sudo fail2ban-client status sshd
sudo fail2ban-client get sshd bantime For persistent bans across reboots, ensure the Fail2ban service is enabled:
sudo systemctl enable --now fail2ban Should you change the default SSH port for security?
Changing the default SSH port from 22 to a non-standard value like 2222 or 2200 does not stop targeted attackers who perform full port scans. However, it dramatically reduces log volume from opportunistic bots that only scan well-known ports. In practice, this makes genuine security alerts easier to spot and reduces storage costs for log aggregation services.
Change SSH port safely without lockout
Before modifying the SSH port, ensure your cloud provider's security group or firewall allows the new port. On AWS, update the EC2 security group first. Then modify the daemon config:
# In /etc/ssh/sshd_config
Port 2222
# Keep port 22 temporarily during transition
Port 22
Port 2222 Reload SSH and test connectivity on the new port before closing your current session:
sudo sshd -t && sudo systemctl reload sshd
ssh -p 2222 user@server-ip Only after confirming the new port works should you remove the legacy Port 22 line and reload again. Update Fail2ban's jail configuration to match. For teams managing multiple servers, codifying this in Terraform or Ansible prevents configuration drift and ensures consistency across environments.
What additional SSH hardening measures complement key auth and Fail2ban?
Key authentication and Fail2ban address authentication and rate limiting, but comprehensive hardening requires addressing protocol-level weaknesses and operational hygiene. These measures are particularly relevant for organizations pursuing SOC 2 or ISO 27001 certification where auditors examine defense-in-depth strategies.
| Hardening Measure | Purpose | Implementation Effort | Audit Relevance |
|---|---|---|---|
| Disable root login | Prevent direct privileged access | Low | High — required by most frameworks |
| Restrict cipher suites | Remove weak encryption algorithms | Medium | High — cryptographic compliance |
| Enable MFA via PAM | Add second factor for sensitive hosts | Medium | High — MFA requirement |
| SSH certificate auth | Centralized key lifecycle management | High | Very High — scalable compliance |
| Bastion/Jump host | Single ingress point for auditing | Medium | High — network segmentation |
Restrict ciphers to modern, secure options only:
Ciphers [email protected],[email protected],[email protected]
MACs [email protected],[email protected]
KexAlgorithms curve25519-sha256,diffie-hellman-group16-sha512 These settings eliminate legacy algorithms vulnerable to known attacks while maintaining compatibility with all modern SSH clients. Test thoroughly with your team's tooling before deploying broadly.
How do you verify SSH hardening is working correctly?
Configuration without verification is just hope. After applying changes, run these validation checks to confirm each hardening layer functions as intended:
- Test key authentication: Attempt SSH from a machine without the private key. Connection must be refused immediately without prompting for a password.
- Verify Fail2ban triggers: Intentionally fail authentication three times from a test IP. Confirm the IP appears in
fail2ban-client status sshdoutput within seconds. - Confirm port restriction: Scan the server with
nmap -p 22,2222 server-ip. Only the configured port should show as open. - Audit cipher negotiation: Run
ssh -vvv user@serverand inspect the debug output to confirm only approved ciphers and MACs are negotiated. - Check log cleanliness: Review
/var/log/auth.logafter 24 hours. Failed attempt volume should drop significantly compared to pre-hardening baselines.
Automate these checks using tools like ssh-audit or integrate them into your CI/CD pipeline if you manage infrastructure as code. Continuous verification ensures hardening persists through updates and configuration changes.
Secure Your Servers With Confidence
Implementing these measures to harden SSH: key auth, Fail2ban, and port hardening eliminates the most common attack vectors targeting Linux servers. The combination of cryptographic authentication, automated threat response, and reduced visibility creates a defense posture that satisfies both security best practices and compliance auditor expectations. Start with key authentication today, add Fail2ban this week, and evaluate port changes during your next maintenance window. If your team needs hands-on support securing cloud infrastructure or preparing for SOC 2 audits, reach out to discuss your specific environment.