A Step-by-step Guide For Securing πŸ” SSH Server

Almost every server πŸ–₯ out there has SSH. Security issues πŸ”“ in your SSH server is a problem πŸ€¦β€β™‚οΈ as it can let anyone get access to the server. This article is a step-by-step πŸ“– guide on securing SSH server by implementing better πŸ› οΈ configuration, πŸ”‘ public/private key authentication and 🎯 fail2ban.

A Step-by-step Guide For Securing πŸ” SSH Server

To modify the behaviour of an SSH server we need to edit the sshd_config file. On a typical Linux server the path to this config file is at: /etc/ssh/sshd_config.

Configuring SSH Server

As the first step to securing an SSH server, we'll modify some SSH server settings to harden security and performance. For each step, I've made a video showing you exactly what to do. Checkout the below video for more information πŸ‘‡

πŸ”’ Securing SSH Server: Configuration
Hey buddy, in this video I have shown you some of the settings & configurations you can make to πŸ”’ secure your SSH server. In the next video for this playlist...

1. Changing the listening port

SSH server by default πŸ“’ listens at port 22, so scripts and botnets on the internet keep trying πŸ”¨ to login through SSH using the default port. By changing the port to any random number between 10,000 πŸ‘‰ 60,000 only specialized attacks πŸ‘¨β€πŸ­ on the server will be possible. A good place to generate a random number is random.org.

Replace the red colored line(s) with the green one(s) πŸ‘‡

- #Port 22
+ Port 21318
Replace "#Port 22" with "Port 21318" without quotes.

2. Switch to Protocol 2

The newer SSH Protocol 2 supports public/private key algorithms better than RSA, along with lot of security holes πŸ•³ being fixed. So in this day and age one shouldn't be πŸ™…β€β™‚οΈ using the older protocol. To use Protocol version 2, add the below line to the configuration file πŸ‘‡ I can simply start typing here πŸ€·β€β™‚οΈ

+ Protocol 2
Add "Protocol 2" anywhere in the file.

3. Specify ListenAddress

Often times, servers have multiple networks adapters and IP addresses. By restricting πŸšͺ SSH to only the desired network adapter we reduce the risk 🚷 of getting unwanted login requests thus making SSH more secure. Β πŸ‘‡ To restrict SSH to a particular network adapter πŸ”Œ.

- #ListenAddress
+ ListenAddress
Replace "#ListenAddress" with "ListenAddress". Where "" is an example IP address.

4. Enable verbose logging

Verbose 🧐 logs are quite helpful for both the πŸ‘¨β€πŸ’» system administrator and fail2ban. By enabling verbose logging we get a better idea πŸ€” of what exactly is happening with the SSH server.

- #LogLevel INFO
+ LogLevel VERBOSE
Replace "#LogLevel INFO" with "LogLevel VERBOSE".

5. Restrict logins through SSH

On a typical 🐧 Linux environment, there will be more than two users in most cases. Telling SSH exactly which user is allowed to login is πŸ‘Œ always better! As users like nobody, www-data, backup are exploited to get into the server.

+ AllowUsers pratham
Add "AllowUsers pratham" anywere in the file. Where "pratham" is an example username.

6. Prevent root login

In UNIX based operating systems, root is an account which has complete control on the machine. If an attacker gets access to the root account pretty much anything & everything is possible. NEVER ⚠️ LOGIN AS root TO YOUR SERVER! For tasks that require elevated permissions, use sudo, su or doas. To disable login access to the root account, set PermitRootLogin to no, like so πŸ‘‡

- #PermitRootLogin prohibit-password
+ PermitRootLogin no
Replace "#PermitRootLogin prohibit-password" with "PermitRootLogin no".

7. Ensure StrictModes is on

Although StrictModes is on by default, some Linux distributions may πŸ€·β€β™‚οΈ override it. When StrictModes is turned on, the SSH server will only start if file permissions are βœ… properly setup. This prevents us from πŸ€¦β€β™‚οΈ accidentally making permissions of config files and SSH keys too open and letting the attacker modify those. To ensure it is turned on, add StrictModes on key to your configuration file or simply uncomment if already exists πŸ‘‡

- #StrictModes on
+ StrictModes on
Uncomment "#StrictModes on" in the configuration file.

8. Reduce maximum retries

No matter how much prepared we are, there will always be script kiddies πŸ˜’ out there. To tackle those and prevent brute forcing we must drop the connection if the user fails to authenticate a set number of times. As you will read 😊 in the next stages we'll implement fail2ban which is a more βš” robust solution for repeated login attempts.

- #MaxAuthTries 6
+ MaxAuthTries 3
Replace "#MaxAuthTries 6" with "MaxAuthTries 3" in the file.

9. Reject empty passwords

Although we will completely πŸ”’ disable password authentication later in this article, disabling empty passwords will make the πŸ•΅οΈβ€β™€οΈ attacker hard to exploit those system accounts with no password. This setting is often applied as a 🦺 safety measure, just in case of a vulnerable account.

- #PermitEmptyPasswords no
+ PermitEmptyPasswords no
Uncomment "#PermitEmptyPasswords no" and ensure it's value is set to "no".

10. Disable X11Forwarding

Most production servers don't have a πŸ–Ό graphical user interface on them. X11Forwarding allows us to run graphical applications on the server and have the interface forwarded to us. An attacker could πŸ€” leverage this to exploit SSH, so when not using it's best to turn off.

- X11Forwarding yes
+ X11Forwarding no
Set "X11Forwarding" to "no".

11. Drop connections when inactive

It is really β›” fatal if SSH connections are left unclosed. Rogue SSH connections can be used by an attacker to gain access to the server. Also, in a situation where the system administrator opens a connection and physically πŸšΆβ€β™‚οΈ leaves the computer, we don't want anyone to give arbitrary commands to our servers. To make the server disconnect automatically after πŸ•‘ 2 minutes of inactivity, set ClientAliveInterval to 120 seconds πŸ‘‡

- #ClientAliveInterval 0
+ ClientAliveInterval 120

12. Disable SSH tunneling

Port forwarding ⏩ using SSH is referred to as "SSH Tunneling". An attacker can use it to hijack a port on the server to forward all it's packets to attacker's computer which can be quite harmful especially if it is 80 or 443 (these are HTTP and HTTPS ports used to serve websites). When not using, it's πŸ‘ best to disable this.

- #PermitTunnel no
+ PermitTunnel no
Ensure "PermitTunnel" is set to "no".

Generating Secure SSH Keys

Now that we have a good base πŸ‘¨β€πŸ­ to work with, the next step is to generate strong and secure SSH keys. Personally for ease of use I don't use a password along with SSH keys, but for added security you can optionally set a password which is safely β›“ encrypted before transmitting.

The video is under production. Link will be updated as soon the video is released.

1. Checking OpenSSH version

The newer the OpenSSH version, the better and newer key algorithms it 🀩 supports. Click here to get a list of which algorithm is supported by what version of OpenSSH. Along with checking the version of OpenSSH installed on your workstation computer, it is required that the server also has the same version or newer. Run the below πŸ‘‡ command to check your installed version of OpenSSH

ssh -V # OpenSSH_8.3p1, OpenSSL 1.1.1g  21 Apr 2020

2. Generating SSH Keys

DSA 🚨 is no longer considered safe these days, RSA ⚠️ is only safe with 4096 and above bit-length, ECDSA's πŸ‘ security depends on your hardware. This leaves us with ED25519 🍏 which is supported by platforms like GitHub, GitLab and BitBucket and is the most recommended algorithm today.

Run the below command to generate an ED25519 key πŸ‘‡

ssh-keygen -o -a 200 -t ed25519 -f ~/.ssh/ssh_key -C "$(whoami)@$(hostname)"

This ☝ should create two files named ssh_key (which is your private key) and ssh_key.pub which is the public key in your current directory.

3. Installing SSH Keys

Now that we have both the public and private keys on our workstation. We need to append the contents of public key into ~/.ssh/authorized_keys file on the server inorder to start using the generated SSH keys. This is as simple as running another command πŸ‘‡

ssh-copy-id -p 21318 -i ~/.ssh/ssh_key.pub pratham@

In the above command ☝ replace pratham@ with your username@ip address and the port number accordingly.

4. Disable Password Login

Completely 🚫 disabling password authentication will reduce the risk of getting brute forced. As without the exact private key that matches the public πŸ— key we installed on the server, authentication won't be successful.

- #PasswordAuthentication yes
+ PasswordAuthentication no
Set "PasswordAuthentication" to "no".

Configuring fail2ban

fail2ban is a software that can read πŸ“° log files and add rules to the firewall. In this article we'll use fail2ban to block repeated SSH authentication requests.

The video is under production. Link will be updated as soon the video is released.

1. Installing fail2ban

sudo apt install fail2ban

Run the ☝ above command to install fail2ban on a Debian/Ubuntu server. A jail is the configuration of fail2ban for a service, and a filter is a file that tells fail2ban exactly what lines to look for in the log files. On a typical installation of fail2ban a jail.conf template is already given, we just need to copy that as jail.local in the directory where fail2ban in installed. To do that run πŸ‘‡ the below command

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

2. Configuring fail2ban for SSH

As we now have the default fail2ban config in place, it's time to configure fail2ban for SSH. To get started open /etc/fail2ban/jail.local in your favorite text editor and find the below snippet of config πŸ‘‡


# To use more aggressive sshd modes set filter parameter "mode" in jail.local:
# normal (default), ddos, extra or aggressive (combines all).
# See "tests/files/logs/sshd" or "filter.d/sshd.conf" for usage example and details.
#mode   = normal
port    = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s

And append the below property to enable the ssh jail πŸ‘‡

enabled = true

This will enable the SSH jail for fail2ban. But we still have one more thing to do. By default fail2ban's SSH filter won't look for key based authentication failures. As we have disabled password authentication we won't get passwords requests, but we'll get private key authentication failures. Modification of the SSH filter is required in this case.

To do that, open /etc/fail2ban/filter.d/sshd.conf in your preffered text editor. In this file find the property named cmnfailre. This property lists all patterns to look for in SSH's log file. Append the below pattern to this list to make fail2ban block on private key authentication failure.

^%(__prefix_line)sConnection closed by authenticating user .+  port \d+ \[preauth\]$


We have finished configuring SSH, generating SSH keys and installing fail2ban and finally configuring fail2ban to automatically block repeated attackers. As a final step, let's restart both SSH and fail2ban services πŸ‘‡

sudo systemctl restart sshd fail2ban