Introduction / Why This Matters
OpenSSH is configured for convenience by default, not for maximum security. This default configuration leaves your server exposed to automated scanners and brute-force attacks that constantly try common password dictionaries every day.
After completing this guide, you will have hardened SSH access with vulnerable features disabled, mandatory key-based authentication, and strict session controls. You will significantly reduce your attack surface and protect your infrastructure from unauthorized access.
Requirements / Preparation
Before you begin, ensure you have:
- Access to the server with
rootprivileges or a user in thesudogroup - A backup of the current configuration:
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak - An SSH client installed on your local machine
- A clear understanding that once password login is disabled, you will not be able to log in without a configured key
⚠️ Important: Always test SSH functionality in a new terminal window before closing your current session. This will prevent you from locking yourself out of the server due to a typo in the configuration.
Step 1: Generating and Configuring Key-Based Authentication
Encryption keys are more reliable than any-length passwords. We will use the Ed25519 algorithm, which offers fast verification and modern cryptographic strength.
- On your local machine, generate a key pair:
ssh-keygen -t ed25519 -C "your_email@example.com" -f ~/.ssh/id_ed25519_fix
- Set strict permissions on the private key:
chmod 600 ~/.ssh/id_ed25519_fix
chmod 700 ~/.ssh
- Copy the public key to the remote server:
ssh-copy-id -i ~/.ssh/id_ed25519_fix.pub user@server_ip
Ensure key-based login works successfully before proceeding.
Step 2: Disabling Vulnerable Parameters in sshd_config
Open the SSH daemon's configuration file in a text editor:
sudo nano /etc/ssh/sshd_config
Find the following directives and change their values. If the lines are missing, add them explicitly:
PermitRootLogin no
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM yes
X11Forwarding no
PermitEmptyPasswords no
PermitRootLogin no— prohibits direct root login.PasswordAuthentication no— completely disables the vulnerable password-based login method.X11Forwarding no— disables graphical interface forwarding if you don't need remote graphics.
Save the file and exit the editor.
Step 3: Restricting Users and Managing Sessions
Only allow access to accounts that genuinely need it. Add the following to the end of sshd_config:
AllowUsers admin deployer
ClientAliveInterval 300
ClientAliveCountMax 2
MaxAuthTries 3
AllowUsers— an explicit whitelist. All other connection attempts will be rejected at the authentication stage.ClientAliveInterval 300andMaxAuthTries 3— the server will terminate inactive sessions after 5 minutes and limit login attempts, disrupting bot activity.
Apply the changes, first checking the syntax:
sudo sshd -t
If the terminal returns no output, there are no errors. Restart the service:
sudo systemctl restart sshd
Verifying the Result
Open a new terminal window and try to connect to the server. Login should happen automatically via your key. To verify security, run on the server:
sudo journalctl -u sshd -f
Try connecting from another device without a key or as a user not listed in AllowUsers. In the logs, you should see connection rejections with codes like Authentication failed or Connection closed.
Potential Issues
Loss of access after applying settings.
Use your hosting provider's web console (VNC/KVM) or emergency recovery mode (Rescue System). Open sshd_config, temporarily set PasswordAuthentication yes back, and restart the service.
Permission denied (publickey) error.
Check permissions on the server. The ~/.ssh directory should have 700 permissions, and the ~/.ssh/authorized_keys file should have 600. On SELinux systems (RHEL, CentOS, AlmaLinux), run restorecon -Rv ~/.ssh.
Server not accepting connections on a non-standard port.
If you changed the port (via the Port directive), ensure the firewall rule allows it (ufw allow 1234/tcp or firewall-cmd --add-port=1234/tcp). SELinux also requires updating the port context with semanage port -a -t ssh_port_t -p tcp 1234.