How to Harden SSH on RHEL 7
SSH (Secure Shell) is the primary remote administration protocol for RHEL 7 servers, and by default its configuration leaves several attack vectors open. Brute-force attacks against exposed SSH ports are constant on any internet-facing host, making SSH hardening one of the first tasks every RHEL 7 administrator should perform. This guide walks through every meaningful change you can make to /etc/ssh/sshd_config, explains why each setting matters, covers changing the default listening port, and shows you how to verify the result without locking yourself out.
Prerequisites
- Root or
sudoaccess to the RHEL 7 host - A working non-root user account with a configured SSH key pair (you will disable password authentication)
- A second terminal or out-of-band console access as a safety net
- SELinux in enforcing mode (default on RHEL 7) — port changes require an SELinux label update
- Basic familiarity with
systemctlandfirewalldoriptables
Step 1: Back Up the Default Configuration
Before editing anything, copy the original configuration file so you can restore it quickly if something goes wrong.
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
Confirm the backup exists and is identical:
diff /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
No output means the files are identical. Keep this backup for the life of the server.
Step 2: Set Protocol Version 2
SSH Protocol 1 has known cryptographic weaknesses and should never be used. Open the configuration file:
sudo vi /etc/ssh/sshd_config
Find or add the following line. On RHEL 7, Protocol 2 is the default, but making it explicit prevents any accidental downgrade:
Protocol 2
Step 3: Disable Root Login
Allowing direct root login over SSH means an attacker only needs to guess one credential — the root password. Disable it:
PermitRootLogin no
If you genuinely need root tasks, log in as a regular user and use sudo or su -. If you must permit root for specific automation, use PermitRootLogin without-password to require a key, but no is the stronger choice.
Step 4: Disable Password Authentication
Password-based authentication is vulnerable to brute force. Requiring SSH key pairs eliminates this entire class of attack. First, confirm your key is in place on the server:
cat ~/.ssh/authorized_keys
Then disable passwords in sshd_config:
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM yes
Keep UsePAM yes so that account expiry and other PAM controls still apply.
Step 5: Restrict Login Attempts and Sessions
Limit how many authentication attempts are allowed before the connection is dropped, and set idle timeout values:
# Disconnect after 3 failed auth attempts
MaxAuthTries 3
# Allow only 2 unauthenticated connections pending auth at once
MaxStartups 2
# Disconnect idle sessions after 5 minutes (300 seconds) with no activity
ClientAliveInterval 300
ClientAliveCountMax 0
Setting ClientAliveCountMax 0 means the server will disconnect immediately when ClientAliveInterval seconds pass without a response, rather than sending multiple keepalive probes first. This terminates forgotten sessions promptly.
Step 6: Restrict Which Users and Groups Can Log In
Use AllowUsers or AllowGroups to create an explicit allow-list. Only accounts matching these directives can authenticate via SSH regardless of any other settings:
# Allow specific users only
AllowUsers alice bob deploy
# Or allow everyone in a specific group (comment out AllowUsers if using this)
# AllowGroups sshusers wheel
Create the group and add users to it if using the group-based approach:
sudo groupadd sshusers
sudo usermod -aG sshusers alice
sudo usermod -aG sshusers bob
Step 7: Set a Login Banner
A legal warning banner displayed before authentication can be important for compliance and establishes that unauthorized access is prohibited. Create the banner file:
sudo vi /etc/issue.net
Add appropriate warning text, for example:
*******************************************************************************
NOTICE: This system is for authorized use only. All activity is monitored and
logged. Unauthorized access will be prosecuted to the fullest extent of the law.
*******************************************************************************
Point sshd at this file in sshd_config:
Banner /etc/issue.net
Step 8: Change the Default SSH Port
Moving SSH off port 22 reduces automated scan noise significantly. Choose a high, unprivileged port (e.g., 2222). First, update SELinux to allow sshd on the new port:
sudo yum install -y policycoreutils-python
sudo semanage port -a -t ssh_port_t -p tcp 2222
sudo semanage port -l | grep ssh
You should see both port 22 and 2222 listed as ssh_port_t. Now update sshd_config:
Port 2222
Open the new port in the firewall and optionally remove port 22 (remove port 22 only after confirming the new port works):
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload
Step 9: Additional Hardening Options
Add these directives to further lock down the daemon:
# Disable X11 forwarding if not needed
X11Forwarding no
# Disable TCP forwarding to prevent tunneling abuse
AllowTcpForwarding no
# Disable agent forwarding
AllowAgentForwarding no
# Ignore per-user authorized_keys in dot-files (use centralized management)
# IgnoreUserKnownHosts yes
# Log authentication events verbosely
LogLevel VERBOSE
# Use only strong ciphers, MACs, and key exchange algorithms
Ciphers aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512,hmac-sha2-256
KexAlgorithms ecdh-sha2-nistp521,ecdh-sha2-nistp384,diffie-hellman-group-exchange-sha256
Step 10: Validate the Configuration and Restart sshd
Before restarting, always validate the configuration syntax to catch typos:
sudo sshd -t
No output means no syntax errors. Now restart the service:
sudo systemctl restart sshd
sudo systemctl status sshd
The status output should show Active: active (running). If it shows failed, check the journal:
sudo journalctl -u sshd -n 50 --no-pager
Step 11: Test the Connection Before Closing Your Session
Open a new terminal window — do not close your existing session yet. Test the connection with verbose output to see exactly what is happening:
ssh -v -p 2222 alice@your-server-ip
Review the verbose output. You should see the protocol version negotiation, the cipher and MAC selection, and the key exchange completing successfully. Confirm you can authenticate with your key and that password authentication is rejected:
ssh -o PasswordAuthentication=yes -p 2222 alice@your-server-ip
# Expected: Permission denied (publickey)
Once you have confirmed access works on the new port, remove port 22 from the firewall if desired:
sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload
Step 12: Automate and Monitor
Enable sshd to start on boot (it is enabled by default on RHEL 7, but verify):
sudo systemctl is-enabled sshd
# Expected: enabled
Install and configure fail2ban from EPEL for additional brute-force protection:
sudo yum install -y epel-release
sudo yum install -y fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
Review SSH authentication logs regularly:
sudo grep "Failed password|Invalid user|Accepted publickey" /var/log/secure | tail -50
SSH hardening on RHEL 7 is a layered process: disabling weak protocols and password authentication eliminates the largest attack classes, while AllowUsers, MaxAuthTries, and ClientAliveInterval reduce exposure further. Changing the default port combined with SELinux labeling and firewall rules creates defense in depth. Regularly audit /var/log/secure and keep sshd updated via yum update openssh-server to stay ahead of newly discovered vulnerabilities. With these steps in place, your SSH surface is dramatically reduced compared to a stock RHEL 7 installation.