Essential SSH Security for Public Web Servers: Public Key Auth, fail2ban, & Port Change
Learn essential SSH security measures for public web servers. This guide covers practical setup steps, from disabling password authentication and enabling public key authentication to implementing fail2ban and changing the SSH port.
*This post contains advertisements
Introduction
Hello, I'm a professional engineer.
Recently, with advancements in AI, the barrier to publishing websites and web services has significantly lowered. While I believe this is generally a good thing, it's also true that there's been an increase in security-related incidents.
Therefore, this time, I'd like to explain essential SSH security practices to prevent unauthorized access.
First, Restrict SSH Connections to "Public Key Authentication" Only
Before implementing fail2ban, the first step is to completely disable password authentication, allowing only clients with a private key to log in via SSH.
As long as password authentication remains active, there's a persistent risk of dictionary and brute-force attacks. By enabling public key authentication only, you can prevent SSH intrusions via password brute-force.
1. Open the SSH configuration file
Edit the SSH configuration file on the server.
sudo nano /etc/ssh/sshd_config
2. Disable password authentication and enable public key authentication
Locate the following configuration items in the file and modify them as shown below (remove # at the beginning of the line to enable them).
# Allow public key authentication
PubkeyAuthentication yes
# Completely disable password authentication
PasswordAuthentication no
# Do not permit empty passwords
PermitEmptyPasswords no
Once modified, save and close the editor.
3. Check configuration file syntax
Check for any errors (like typos) in the configuration using a test command.
sudo sshd -t
※ If the prompt returns without any errors, the configuration is correct.
4. Restart the SSH daemon
Apply the changes.
sudo systemctl restart ssh
5. Test in a separate window without closing the current one
To prevent being locked out due to a configuration error, keep your current terminal session open as a lifeline.
Open a new terminal window (e.g., Tera Term) and verify the following:
-
Connection with private key: Ensure you can log in.
-
Password authentication attempt: Ensure the connection is rejected (e.g.,
Permission denied (publickey)).
Only after confirming a successful connection with your private key will you be protected against SSH password brute-force attacks. This is the absolute minimum you should do!
fail2ban Installation and Initial Setup
Next, we'll configure fail2ban. While public key authentication alone provides significant benefits, it's recommended to set up fail2ban for enhanced operational stability, resource protection, and layered defense.
What exactly is "fail2ban"?
fail2ban is an intrusion prevention tool that runs on Linux servers.
Its mechanism is both simple and powerful:
-
Continuously monitors logs
It constantly monitors SSH authentication logs (e.g.,
/var/log/auth.log) and counts failed login attempts. -
Identifies IPs exceeding a threshold
Access source IP addresses that meet conditions like "5 failed logins in 10 minutes" are targeted for banning.
-
Dynamically adds firewall rules to block access
It temporarily drops (rejects) communication from that IP (e.g., for 24 hours or a week), blocking access to the server itself.
-
Automatically unbans after the set time expires
Administrators do not need to manually unblock every time.
1. Installation
First, update your packages and install fail2ban.
sudo apt update
sudo apt install -y fail2ban
2. Create the configuration file
fail2ban's default configurations are in /etc/fail2ban/jail.conf, but directly editing this file is an anti-pattern as it may be overwritten during package updates.
It's best to create a new jail.local file containing only the necessary settings.
sudo nano /etc/fail2ban/jail.local
3. Recommended Basic Parameter Settings
Adjust the following three key parameters in the [DEFAULT] section of the configuration file.
[DEFAULT]
# Time in seconds for an attacker to be banned (can also specify 1d, 1w, etc.)
bantime = 1d
# Monitoring window period for counting suspicious access
findtime = 10m
# Number of failures within the period before banning
maxretry = 5
# If you have fixed IPs that you never want to be banned, specify them separated by spaces.
# ignoreip = 127.0.0.1/8 ::1 your_fixed_IP
-
bantime: The initial 10-minute ban time often leads bots to re-attack persistently. For production use, it's recommended to extend this to at least 1 day (1dor86400). -
ignoreip: If your home or office IP is static, adding it here can prevent the unfortunate event of accidentally banning yourself during configuration.
4. Enable SSH monitoring ([sshd] section)
Scroll down to the [sshd] section. Configure (or add) it as follows:
[sshd]
enabled = true
port = ssh
port = ssh (which monitors the default port 22) is fine.Once editing is complete, save and close the editor.
5. Start the service and enable auto-start
Apply the settings and enable the service to start automatically on server reboot.
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
6. Verify operation
Execute the following command to check if SSH monitoring is functioning correctly.
sudo fail2ban-client status sshd
If it's running normally, a status similar to this will be displayed:
Status for the jail: sshd
|- Filter
| |- Currently failed: 0
| `- Total failed: 0
`- Actions
|- Currently banned: 0
`- Total banned: 0
`- Banned IP list:
fail2ban deployment is now complete.
After configuration, occasionally run the check command above to observe activity. You'll likely find more bot attacks than you anticipated!
Steps for SSH Port Change and fail2ban Adjustment
While fail2ban is now configured, staying on the default SSH port will still result in many bot attacks and noisy logs. Therefore, it's recommended to change the SSH port to minimize access attempts.
1. First, allow the new port in the OS firewall (UFW)
Before changing SSH settings, allow traffic on the new port. I plan to write a separate article about UFW later.
sudo ufw allow 65432/tcp
sudo ufw status
SSH Configuration Change (sshd_config)
Open the configuration file and specify the port number.
sudo nano /etc/ssh/sshd_config
Find the line #Port 22, uncomment it (remove #), and specify the new port you just allowed.
Port 65432
Adjust fail2ban's monitored port
Open the fail2ban configuration (jail.local) and change the monitored port in the [sshd] section to the new number.
sudo nano /etc/fail2ban/jail.local
[sshd]
enabled = true
port = 65432
Restart various services
Apply the settings with the following commands. Note that executing these commands will not disconnect your current SSH session. Keep it open.
sudo sshd -t
sudo systemctl restart ssh
sudo systemctl restart fail2ban
Test connection in a separate window without closing the current one
Leave your current terminal session open as a lifeline, and open a new window to test if you can log in using the new port (65432).
Once you've successfully logged in, use the original terminal to delete the rule for the old port 22 and close it.
# Check rules with numbers
sudo ufw status numbered
# Delete the rule numbers corresponding to port 22 (OpenSSH) in descending order
sudo ufw delete
The SSH port change is now complete.
Summary
In this guide, we implemented SSH security measures by performing the following tasks:
-
SSH Public Key Authentication: Disabled SSH password authentication to prevent brute-force intrusions.
-
fail2ban: Automatically and temporarily blocks sources that repeatedly fail authentication.
-
SSH Port Change: Reduced automated scans and login attempts targeting port 22, thereby minimizing log noise.
Implementing such a layered defense reduces unnecessary login attempts and strengthens protection against unauthorized SSH access.
Especially for web services operated by individuals, you bear the security risks yourself. At a minimum, I recommend properly configuring SSH authentication settings.
Finally
Despite writing all this, I am not an infrastructure engineer, so I've never configured these in a professional capacity, haha.
Privately, I have to configure these things myself, which is quite a hassle! Well, I guess it's all part of learning...
This article was translated from the original Japanese version (WEB公開したらやっておきたいSSHセキュリティ|公開鍵認証・fail2ban・SSHポート変更) using Gemini API.