Step 5: Change the SSH port (optional)
Moving off port 22 won't stop a determined attacker, but it cuts automated bot noise by 90%+. In sshd_config:
# Listen on the new port first, keep 22 as a safety net
Port 22
Port 2222
Reload sshd, verify the new port accepts connections, then remove the Port 22 line and reload again.
If you use a firewall, open the new port:
# ufw
sudo ufw allow 2222/tcp
sudo ufw delete allow 22/tcp
# firewalld
sudo firewall-cmd --add-port=2222/tcp --permanent
sudo firewall-cmd --remove-port=22/tcp --permanent
sudo firewall-cmd --reload
Remember to update your ~/.ssh/config on your local machine with the new port.
Step 6: Set up fail2ban for SSH
fail2ban watches your logs and temporarily bans IPs that show malicious behavior — repeated failed logins, probe patterns, and so on.
# Install fail2ban
sudo apt install fail2ban # Debian/Ubuntu
sudo dnf install fail2ban # RHEL/Fedora
Create a local jail override so your settings survive package updates:
# /etc/fail2ban/jail.local
[sshd]
enabled = true
port = 2222 # Change to your actual SSH port
bantime = 3600 # Ban for 1 hour
findtime = 600 # Count failures within 10 minutes
maxretry = 3 # Allow 3 attempts before banning
If you kept SSH on port 22, omit the port line — the default matches the standard port. Enable and start fail2ban:
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
Check its status:
sudo fail2ban-client status sshd
Step 7: Lock down authorized_keys
You can restrict what a key is allowed to do by adding options to ~/.ssh/authorized_keys. Prefix the key line with comma-separated options:
# Restrict this key to a specific command only (no shell access)
command="/usr/local/bin/backup.sh",no-port-forwarding,no-X11-forwarding ssh-ed25519 AAAAC3...
# Restrict this key to connections from a specific IP
from="203.0.113.50" ssh-ed25519 AAAAC3...
# Combine both
from="203.0.113.50",command="/usr/local/bin/backup.sh",no-port-forwarding ssh-ed25519 AAAAC3...
Useful options:
| Option | Effect |
|---|---|
from="IP" |
Only allow connections from this address |
command="cmd" |
Run this command instead of a shell — great for automated scripts |
no-port-forwarding |
Prevent SSH tunneling through this connection |
no-agent-forwarding |
Prevent the client from using SSH agent forwarding |
no-X11-forwarding |
Block X11 forwarding |
Step 8: Set up ~/.ssh/config on your local machine
Instead of typing long commands every time, create ~/.ssh/config:
Host myserver
HostName yourserver.com
Port 2222
User yourusername
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
Host linode
HostName 104.200.20.169
User root
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
Now you connect with just:
ssh myserver
IdentitiesOnly yes prevents SSH from offering keys from your agent that don't match — useful if you have multiple keys and some servers reject you for too many failed attempts before the right key is found.
Step 9: Multi-hop connections with ProxyJump
If you need to reach a server behind a bastion host or jump box, avoid SSH agent forwarding. Use -J instead:
ssh -J bastionuser@bastion.example.com targetuser@10.0.0.5
Or in ~/.ssh/config:
Host bastion
HostName bastion.example.com
User bastionuser
Host internal
HostName 10.0.0.5
User targetuser
ProxyJump bastion
Agent forwarding (-A) exposes your agent socket to the intermediate host — anyone with root on the bastion can use your keys while you're connected. ProxyJump tunnels the connection without exposing your credentials.
Going Further
- Two-Factor Authentication:
google-authenticator-libpamor FIDO2 hardware keys viasshd_configAuthenticationMethods - Port Knocking:
knockdkeeps the SSH port closed until a specific sequence of connection attempts is received - Single Packet Authorization:
fwknopsends a single encrypted packet to open the port — more advanced and harder to detect than port knocking - SSH certificates: OpenSSH supports signed host and user certificates for environments with many servers
Troubleshooting: I Locked Myself Out
If you still have a session open, revert your changes and reload sshd. If not, most VPS providers offer a web-based console or rescue mode that bypasses SSH entirely — use that to fix /etc/ssh/sshd_config and restart the service.
This guide is maintained as part of a modular, SSL-first framework. Each configuration is audited for production stability and modern security standards.