How to secure SSH server
SSH, or Secure SHell, is the most common communication protocol used to connect to servers. It is the telnet’s successor. The problem with telnet is that the data exchanged between you and the server was not authenticated and encrypted. In other words, in case of MITM (Man In The Middle) attack, the bad guy between the server and you could see everything.
Obviously, it’s not because we use a recommended tool that we don’t have to configure it. It is what we are going to see in this article.
Information and requirements
These elements are to be taken into consideration to follow this article:
- The manipulations are carried out on Rocky Linux 8.
- The package
openssh-server
is installed by default, if not, install it. - Do not forget to restart the
sshd
service to take account of the modifications (sudo systemctl restart sshd
).
Update the system
adrien@archiso ~ $ sudo dnf -y update
About the users
The most important thing you must always keep in mind is that: you will never log in as root. You have no trouble understanding that if the root account is compromised, your system and all the installed services are also compromised, without necessarily realizing it (if the usurper is smart).
The best method would be to create a service account (which can use the sudo
command to perform administrative tasks). Maybe, you already have this kind of user, you can use this one to connect to. Otherwise, it is what we will see right away.
adrien@archiso ~ $ adduser -r -s /bin/bash -c "Standard user account" -U -m -G wheel <username>
adrien@archiso ~ $ passwd <username>
Concerning this command:
- Replace
<username>
with the username of your choice. - Users in the
wheel
group can perform administrative tasks usingsudo
.
Note: I read in several articles that it was advised not to use a too generic username (admin, administrator, sysadmin…). I partially agree. First of all, it is not a good idea to create a username with random characters like GxTjaiKHg
. Also, there are lists of well known usernames on the Internet that are most commonly used to perform brute-force attacks. So I prefer to take the risk of choosing an intelligible username.
SSH daemon configuration
The configuration file of the SSH daemon is located at /etc/ssh/sshd_config
. In this one, do the following modifications.
Disable root login
Again, the root user should never be allowed to log in directly over a network, as this both reduces auditable information about who ran privileged command on the system and allows direct attack attempts on root’s password.
PermitRootLogin no
Authorize SSH key based authentication
Specifies whether public key authentication is allowed.
PubkeyAuthentication yes
Disable empty passwords
When password authentication is allowed, it specifies whether the server allows login to accounts with empty password strings.
PermitEmptyPasswords no
Disable password authentication
Specifies whether password authentication is allowed.
PasswordAuthentication no
Authentication that must be completed
Specifies the authentication methods that must be successfully completed for a user to be granted access.
AuthenticationMethods publickey
Disable host-based authentication
SSH’s cryptographic host-based authentication is slightly more secure than .rhosts
authentication, since hosts are cryptographically authenticated. However, it is not recommended that hosts unilaterally trust one another, even within an organization.
HostbasedAuthentication no
Disable .rhosts files
SSH can emulate the behavior of the obsolete rsh
command in allowing users to enable insecure access to their accounts via .rhosts
files.
IgnoreRhosts yes
Disable X11 forwarding
Specifies whether X11 forwarding is permitted. If you don’t use X11 forwarding, I advise you to disable it.
X11Forwarding no
Do not allow users to set environment options
To prevent users from being able to present environment options to the SSH daemon and potentially bypass some access restriction.
PermitUserEnvironment no
Set a banner
The content of the specified file is sent to the remote user before authentication is allowed.
Banner /etc/ssh/banner
I advise you to put something like this in the file /etc/ssh/banner
.
Any unauthorized access to this system is prohibited and will be prosecuted by law.
By attempting to access or accessing this system, you agree that your actions will be monitored and any suspicious use will be reported.
Note: Some of you might think that it’s pretty useless to print this kind of message before authentication. As earlier, I partially agree. In fact, maybe 99.9% of unauthorized access attempts are made by robots and they don’t give a fuck about the banner. But, the last 0.1% (that are human being) will see your banner and that will probably discourage them. And since “Anything that isn’t forbidden is allowed”, if someone gains access to your system, he won’t be able to say that it wasn’t forbidden (although the moral law stipulates it)…
Other recommendations
Changing the port
I have already read in some articles that changing the default port (22) is a good practice. Again, I partially agree because knowing that with a tool like RustScan it is possible to scan 65535 ports in a very short time, it is easy to find the SSH port. So it’s just a way to make the attacker losing a few seconds…
Port knocking
Port knocking is a method that aims at modifying the behavior of a firewall in real time by causing the opening of ports for communication by first launching series of connections on distinct ports in the right order, like knocking on a door. I’ve already written an article on this subject that you can find here.
SSH, shut your mouth
When SSH tries to authenticate via public key, it sends the server all your public keys, one by one, until the server accepts one. One can take advantage of this to enumerate all the client’s installed public keys. If this behavior is problematic for you, you can tell SSH not to present your public keys to the server by default.
Add these lines at the end of your ~/.ssh/config
(after other Host
directives).
Host *
PubkeyAuthentication no
IdentitiesOnly yes
And then specify what keys should be used for each host.
Host example.com
PubkeyAuthentication yes
Hostname <IP address>
User <user>
Port <port>
IdentityFile </path/to/private/key>
Reminders
Generate a strong SSH key pair
Now that you understand that you need to use an SSH key pair to connect to your servers and not a password, it is important to generate strong cryptographic keys.
adrien@archiso ~ $ ssh-keygen -t ed25519 -a 100 -f ~/.ssh/<key pair name> -C <comment>
<passphrase>
<confirm>
This will create a private and public key pair files using the Ed25519 algorithm, which is considered state of the art. Elliptic curve algorithms in general are sleek and efficient and unlike the other well known elliptic curve algorithm ECDSA, this Ed25519 does not depend on any suspicious NIST defined constants.
The -a
flag specifies the number of KDF (Key Derivation Function) rounds used. Higher numbers result in slower passphrase verification and increased resistance to brute-force password cracking if the keys are stolen. Applying 100 rounds is a good compromise between security and efficiency.
The -C
allows you to provide a comment, put what you want.
Best way to copy the public key to a server
When password authentication is enabled on a server (just after a fresh install), you can copy the public key to it like the following.
adrien@archiso ~ $ ssh-copy-id -i ~/.ssh/<key pair name>.pub <user>@<IP address>
<user's password>
The public key is now copied into /home/<user>/.ssh/authorized_keys
file.