SSH is the primary remote access method for Linux servers, making it a common target for brute-force attacks, credential stuffing, and exploitation attempts. On RHEL 9, the default OpenSSH configuration works out of the box but leaves several attack vectors open. Hardening your SSH server configuration significantly reduces the risk of unauthorized access and is one of the most impactful security steps you can take on any Internet-facing system. This tutorial walks through a comprehensive SSH hardening checklist for RHEL 9.
Prerequisites
- A RHEL 9 server with root or sudo access
- A non-root user account with a configured SSH key pair
- Physical or out-of-band console access as a fallback (in case you lock yourself out)
openssh-serverinstalled and running (systemctl status sshd)
Step 1 — Back Up and Edit the sshd_config File
Before making any changes, create a backup of the default configuration so you can restore it if needed.
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
sudo nano /etc/ssh/sshd_config
Apply the following settings, adding or uncommenting lines as required:
# Change default port (use a high, non-standard port)
Port 2222
# Only allow SSH protocol 2
Protocol 2
# Disable direct root login
PermitRootLogin no
# Disable password authentication — keys only
PasswordAuthentication no
PermitEmptyPasswords no
# Restrict access to specific users
AllowUsers deployer alice
# Limit authentication attempts
MaxAuthTries 3
MaxSessions 5
# Idle session timeout
ClientAliveInterval 300
ClientAliveCountMax 2
# Disable forwarding features you don't need
X11Forwarding no
AllowAgentForwarding no
AllowTcpForwarding no
# Disable unused authentication methods
KerberosAuthentication no
GSSAPIAuthentication no
# Log level for auditing
LogLevel VERBOSE
Save the file and validate the syntax before restarting the daemon:
sudo sshd -t
If no errors are reported, reload the service:
sudo systemctl restart sshd
Step 2 — Restrict Access with hosts.allow and hosts.deny
TCP Wrappers provide an additional network-level filter. Edit /etc/hosts.allow to whitelist trusted networks, then deny everything else in /etc/hosts.deny.
# /etc/hosts.allow — permit SSH from your office/home IP range
sshd : 203.0.113.0/24
# /etc/hosts.deny — block all other SSH connections
sshd : ALL
Replace 203.0.113.0/24 with your actual trusted IP range. If you manage servers from dynamic IP addresses, consider using a jump host or VPN instead of TCP Wrappers for access control.
Step 3 — Install and Configure Fail2ban
Fail2ban monitors log files for repeated failed authentication attempts and automatically blocks offending IP addresses using firewalld or iptables rules.
sudo dnf install -y epel-release
sudo dnf install -y fail2ban
sudo systemctl enable --now fail2ban
Create a local jail configuration for SSH (always override in .local files to survive package upgrades):
sudo nano /etc/fail2ban/jail.local
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 3
[sshd]
enabled = true
port = 2222
logpath = %(sshd_log)s
backend = %(sshd_backend)s
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
Step 4 — Audit Your SSH Server with ssh-audit
The ssh-audit tool scans your server and reports on key exchange algorithms, ciphers, MACs, and other security parameters — flagging anything that is weak or deprecated.
sudo dnf install -y python3-pip
pip3 install ssh-audit
# Run audit against localhost (using the custom port)
ssh-audit localhost -p 2222
Alternatively, you can run it from a remote machine against your server’s public IP. Review the output and update the KexAlgorithms, Ciphers, and MACs directives in sshd_config to remove any flagged weak algorithms:
# Example: restrict to modern algorithms only
KexAlgorithms curve25519-sha256,diffie-hellman-group16-sha512
Ciphers [email protected],[email protected]
MACs [email protected],[email protected]
Reload sshd after any cipher changes:
sudo sshd -t && sudo systemctl reload sshd
Step 5 — Verify Access Before Closing Your Session
Always test the new configuration from a second terminal before closing your current session. This ensures you can still log in with your key on the new port.
# From a second terminal on your local machine
ssh -p 2222 -i ~/.ssh/id_ed25519 alice@your-server-ip
# Check the sshd journal for any errors
sudo journalctl -u sshd -n 50 --no-pager
If login succeeds, close the original session. If it fails, use your console backup access to review /etc/ssh/sshd_config for typos and restore from the backup if necessary.
Conclusion
Hardening SSH on RHEL 9 involves a combination of configuration changes, network filtering, and automated response to brute-force attempts. By disabling root login, requiring key-based authentication, changing the default port, limiting connection attempts, and auditing cipher strength, you substantially raise the cost of any attack against your SSH service. Run ssh-audit periodically — especially after OpenSSH package updates — to ensure no weak algorithms have been re-enabled.
Next steps: How to Set Up WireGuard VPN on RHEL 9, How to Configure SELinux on RHEL 9, and How to Set Up Linux Firewall Rules with firewalld.