This article is part of a series.
- SSH Series
- Part 1: Introduction to SSH
- Part 2: Setting Up and Using SSH
- Part 3: SSH Key Based Authentication
- Part 4: SSH Best Practices and Security Hardening
- Part 5: Advanced SSH Techniques
- Part 6: Troubleshooting Common SSH Issues
- Part 7: Automating Tasks With Automation
- Part 8: SSH Alternatives and Enhancements
- Part 9: Recap, Further Resources, and Closing Thoughts

In the previous parts of SSH series, I introduced SSH, demonstrated setup procedures, and explored key-based authentication. Now, it’s time to delve into security hardening—a critical practice for any production system. A properly hardened SSH setup helps protect against brute-force attacks, unauthorized root access, and other common threats. In this post, I’ll walk you through recommended SSH configuration options, port changes, Fail2Ban, multi-factor authentication, and logging strategies.
Overview of SSH Configuration and Recommended Settings
The main SSH daemon configuration file on most Linux systems is located at:
/etc/ssh/sshd_config
You can fine-tune your SSH security using directives in this file.
Key directives include:
PermitRootLogin no
Prevents direct root logins, forcing attackers to guess both a normal user and escalate privileges separately.PasswordAuthentication no
Disables password authentication in favour of key-based logins. Once you’re comfortable with SSH keys, consider turning off passwords entirely for enhanced security.PubkeyAuthentication yes
Ensures the server accepts key-based logins (enabled by default on most distributions).Port 22
(default) You can change this to a non-standard port (e.g.,2222
) to reduce noise from automated scans (more on this below).
Why Hardening Matters
-
Brute-Force Attacks
Attackers often run scripts that try common usernames and passwords on port 22. Hardening measures like key-based auth, fail2ban, and non-standard ports help mitigate this. -
Least Privilege
Limiting who can connect, and how, ensures you minimize the blast radius if an account is compromised. -
Compliance and Audit
Many industry regulations (e.g., HIPAA, PCI-DSS) require secure remote access and thorough logging of administrative actions.
Step-by-Step Guide to Hardening SSH
Changing the Default Port
By default, SSH listens on port 22. While security by obscurity isn’t a silver bullet, using a non-standard port can significantly reduce automated attacks. Consider using something like 2222
or 2202
.
-
Edit
/etc/ssh/sshd_config
:sudo nano /etc/ssh/sshd_config
-
Set:
Port 2222
-
Restart SSH:
sudo systemctl restart ssh
-
Update Firewall Rules
-
For ufw
sudo ufw allow 2222/tcp sudo ufw delete allow 22/tcp
-
For iptables:
sudo iptables -A INPUT -p tcp --dport 2222 -j ACCEPT sudo iptables -A INPUT -p tcp --dport 22 -j DROP
-
-
Connect on the New Port
ssh -p 2222 user@server-ip
[!Tip]
Always keep a backup session open in case you misconfigure the new port and lock yourself out.
Pros and Cons of Non-Standard Ports
- Pros:
- Reduces noise from automated scanners.
- Makes it slightly harder for opportunistic attackers.
- Cons:
- Not true “security,” just obscurity—committed attackers can still find your port.
- Requires updating all your scripts/tools to specify the new port.
Disabling Root Login
Allowing direct root login is risky—once inside, an attacker has full control. A safer practice is to log in as a regular user and then escalate privileges using sudo
or su
as needed.
-
Edit
/etc/ssh/sshd_config
sudo nano /etc/ssh/sshd_config
-
Find (or add) the line
PermitRootLogin no
-
Restart SSH
sudo systemctl restart ssh
-
Verify
Attemptingssh root@server-ip
should fail. Instead, log in as a non-root user
Protecting Against Brute-Force Attacks with Fail2Ban
Fail2Ban scans log files (like /var/log/auth.log
) for repeated failed login attempts and blocks offending IP addresses temporarily.
-
Install Fail2Ban
-
Ubuntu/Debian
sudo apt update -y sudo apt install fail2ban
-
CentOS/RHEL:
sudo yum install fail2ban
-
-
Configure Fail2Ban:
-
Copy the default config:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
-
Edit
/etc/fail2ban/jail.local
:[sshd] enabled = true port = 2222 filter = sshd logpath = /var/log/auth.log maxretry = 3 bantime = 600
port
: Match the port from yoursshd_config
(e.g.2222
)maxretry
: Number of failed attempts before banningbantime
: Ban duration in seconds (600 = 10 minutes)
-
-
Start Fail2Ban:
sudo systemctl enable fail2ban sudo systemctl start fail2Ban
-
Check Status:
sudo fail2ban-client status sshd
You’ll see how many IPs, if any, are currently banned.
[!Tip] If you need to unban an IP
sudo fail2ban-client set sshd unbanip <IP_ADDRESS>
SSH Configuration Directives
Let’s look more closely at some sshd_config directives that go beyond basic settings:
-
AllowUsers
orAllowGroups
- Restricts SSH access to specified users or groups:
AllowUsers alice bob
- Restricts SSH access to specified users or groups:
-
DenyUsers
orDenyGroups
- If you prefer to block specific accounts, similarly:
DenyUsers root test
- If you prefer to block specific accounts, similarly:
-
ClientAliveInterval
andClientAliveCountMax
- Helps manage idle sessions. If a client is inactive for a specified duration, the server ends the session.
Example:
This disconnects idle sessions after approximately 10 minutes (300s × 2 = 600s).
ClientAliveInterval 300 ClientAliveCountMax 2
- Helps manage idle sessions. If a client is inactive for a specified duration, the server ends the session.
Example:
-
LoginGraceTime
- Time allowed for someone to successfully log in before the server disconnects. Helps limit brute-force attempts.
LoginGraceTime 60
- Time allowed for someone to successfully log in before the server disconnects. Helps limit brute-force attempts.
Adding Multi-Factor Authentication (2FA)
Even with strong SSH keys, an extra authentication factor can enhance security further. Google Authenticator (or similar) provides a Time-based One-Time Password (TOTP) that changes every 30 seconds.
Installing Google Authenticator on the Server
-
Install the Package:
-
Ubuntu/Debian
sudo apt-get install libpam-google-authenticator
-
CentOS/RHEL
sudo yum install google-autheticator
-
-
Configure for Your User:
google-authenticator
- This generates a QR code and secret key. You’ll scan this with the Google Authenticator app on your phone.
- Answer the prompts to set up constraints like rate limiting, forced new tokens, etc.
Update SSH PAM Settings
-
Edit
/etc/pam.d/sshd
:# Add the following line at the top or appropriately auth required pam_google_authenticator.so
-
Edit
/etc/ssh/ssh_config
:ChallengeResponseAuthentication yes
If you rely on keys + TOTP:
AuthenticationMethods publickey,keyboard-interactive
or if you still allow passwords + TOTP:
AuthenticationMethods password,keyboard-interactive
-
Restart SSH:
sudo systemctl restart ssh
Logging In with 2FA
Now, every time you attempt to SSH, after providing your key or password, you’ll also be prompted for a verification code from the authenticator app. This significantly raises the bar for attackers, since they need physical access to your TOTP device.
Logging and Auditing
Monitoring Log Files
-
Ubuntu/Debian:
/var/log/auth.log
-
CentOS/RHEL:
/var/log/secure
Look for entries like:
sshd[1234]: Failed password for invalid user test from 192.168.1.50 port 51234 ssh2
Or
Accepted publickey for alice from 203.0.113.10 port 55276 ssh2
These logs show failed and successful login attempts.
Tools for Detecting Suspicious Activity
- Logwatch: Generates daily email summaries of system logs.
- Splunk/Elastic Stack: Centralized log ingestion and analysis.
- Security Onion: A comprehensive platform for threat hunting and log correlation.
By regularly reviewing logs, you can spot unusual login attempts or repeated failures indicating potential brute-force attacks—even if Fail2Ban is already in place.
Conclusion
Securing SSH isn’t a single step—it’s a continuous process of configuration, monitoring, and updating. By:
- Changing default ports (optional, but helpful),
- Disabling root logins,
- Enforcing key-based authentication,
- Using Fail2Ban,
- Implementing 2FA,
- And regularly monitoring logs,
you significantly reduce your attack surface and ensure a more robust security posture.
In Part 5, I’ll move on to advanced SSH techniques such as port forwarding, jump hosts, and configuring ~/.ssh/config
for streamlined workflows. Until then, review your current SSH settings and log files to make sure you’re on top of your server’s security!
Further Reading
Stay tuned for more on harnessing the full power of SSH, and drop any questions or tips in the comments below!
Have questions or want to share your own SSH hardening tips? Leave a comment below, and let’s keep the conversation going.
This article is part of a series.
- SSH Series
- Part 1: Introduction to SSH
- Part 2: Setting Up and Using SSH
- Part 3: SSH Key Based Authentication
- Part 4: SSH Best Practices and Security Hardening
- Part 5: Advanced SSH Techniques
- Part 6: Troubleshooting Common SSH Issues
- Part 7: Automating Tasks With Automation
- Part 8: SSH Alternatives and Enhancements
- Part 9: Recap, Further Resources, and Closing Thoughts
comments powered by Disqus