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 sudo access 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 systemctl and firewalld or iptables

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.