Configure OpenSSH Server on Linux with Maximum Security

SSH or also known as Secure Shell , is a protocol and the name of the program that implements it. SSH is widely known for being the secure protocol for the remote administration of servers, routers, switches and a long list of computers. The SSH protocol allows you to completely manage the server or network device through a command interpreter, in addition, we can also redirect X traffic to execute graphic programs through the SSH session itself.

Other fundamental characteristics of SSH are that it will allow us to safely copy data, both files and folders, through the SFTP protocol (SSH FTP), a protocol made from scratch and that has nothing to do with FTPS or FTPES (FTP over SSL / TLS). The SSH protocol is essential in the field of networks and systems, in addition, we can configure it in detail to provide our system with the maximum possible security.

Configure OpenSSH Server on Linux with Maximum Security

The SSH protocol provides confidentiality (the data is encrypted point to point), authentication (we can authenticate in front of the SSH server in multiple ways, with user / key, public key cryptography and we can even configure a second authentication factor), integrity (yes the data being modified or modified by a malicious user can be detected as it uses HMAC to check the integrity of each and every data).

There are two versions of SSH, version 1 is not recommended today, in fact, by default the SSHv2 version is always used. By default SSH uses the TCP protocol of the transport layer, and the port number is 22, however, we can change the port number to mitigate possible bot scans to the SSH service.

In this manual that we present today, we are going to teach you how to configure the OpenSSH SSH server, a program that is available for operating systems based on Unix and Linux, such as FreeBSD, OpenBSD, Debian, Red Hat Enterprise Linux and a long etc. of distributions. In this guide we will not only learn to correctly configure the sshd_config configuration file, but we will also use additional programs to provide the system with the maximum possible security. In this manual all the configurations will be done with Debian, however, all the security measures can be implemented in any operating system based on Linux and Unix.

OpenSSH installation and startup

OpenSSH is the SSH server / client program most used by routers, switches, servers and a long etcetera of devices. This program is completely free and open source. The installation of this SSH server (if you don’t already have it installed by default) is very simple, we just have to put the following command in a terminal:

sudo apt install openssh-server

Once installed, we must take into account certain directories and commands to start, stop and restart the SSH service.

To edit the configuration of the SSH server we must do in console:

sudo nano /etc/ssh/sshd_config

Another directory that we have to take into account is that of known hosts, since this is also where we will configure the RSA / DSA cryptographic keys. The directory where the known hosts and public keys are located is as follows:

/home/usuario/.ssh/

This directory by default is hidden (.ssh) and there is a directory for each user that is in the operating system and that connects to a remote server.

To start the server:

sudo /etc/init.d/ssh start

To stop the server:

sudo /etc/init.d/ssh stop

To restart the server:

sudo /etc/init.d/ssh restart

Once we have installed the SSH server, we know where the server configuration files are and the directory where the public keys are stored, we go with the configuration of the sshd_config since it is the fundamental configuration file of OpenSSH.

Sshd_config configuration for maximum security

Change the default port of the SSH server

By default SSH servers use port 22 for connections. It is advisable to change this port number, to prevent bots or cybercriminals from trying to log in, although this alone does not provide security, we can go unnoticed by massive scans from the Internet. If, for example, we want to use port 22445, we must put the following in the configuration file:

  • Port 22445

Block root access on remote connections

By default, any user in the operating system who has Shell permissions, will be able to log in to the server. In addition, we must bear in mind that if we have the root user activated, it will also be able to connect to the server locally or remotely, avoiding the attacker having to “guess” the username. By default, bots always try to attack port 22 and the “root” user.

By disabling the root user itself, and using “sudo” to elevate to superuser permissions, we will avoid this. In addition, OpenSSH will also allow us to disable the root user login to provide the system with greater security:

  • PermitRootLogin no

In this way, root connections will be blocked, preventing unauthorized users from carrying out brute force attacks against our SSH server to guess the credentials of the root user. We also have other options in this section, such as ” PermitRootLogin without-password ” where authentication is allowed but not with username and password, but with RSA cryptographic keys.

Additional security settings

There are other recommended configurations to avoid unwanted connections to our SSH server. These connections are:

  • LoginGraceTime : We will establish the time necessary to enter the password, avoiding that the attacker has to “think a lot”.
  • MaxAuthTries : Number of attempts allowed when entering the password before disconnecting.
  • MaxStartups : Number of simultaneous logins from an IP, to avoid brute force being used with several sessions at the same time.
  • AllowUsers : It is to create a user whitelist. This parameter allows us to configure the users that will be able to connect. A very restrictive measure but at the same time very safe since it will block all the connections of the users who are not in the list. The users that we have here will be able to connect, and the rest will not.
  • DenyUsers : Similar to the previous one, but now we create a blacklist. The users that we have here will not be able to connect, and the rest will.
  • AllowGroups / DenyUsers : Exactly the same as above, but instead of creating a black / white list of users, it is user groups.

For example, a configuration file for sshd_config would be the following:

Port 22445
PermitRootLogin no
LoginGraceTime 30
MaxAuthTries 3
MaxStartups 3
AllowUsers sergio sergio2
DenyUsers adrian adrian2

An additional security measure is to configure the key exchange algorithms, symmetric encryption, and also the HMAC configuration for integrity checking. Currently it is recommended to apply the following configuration to have a very high security:

KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256 Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com

With this configuration we will have the best cryptographic suites for the server, however, old clients may not be able to connect as they do not support these algorithms. We must take this detail into account, and test which algorithms are compatible and which are not.

If we have created new RSA or DSA keys for ones with greater bit length, we must put it in the configuration file (or replace the previous ones, and thus we will not have to touch the configuration file), in this way we will obtain additional security if for example we use RSA keys of 4096 bits or higher.

HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key

To generate new 4096-bit RSA keys, we will simply have to execute the following command:

ssh-keygen -f /etc/ssh/ssh_host_rsa_key -t rsa -b 4096

If we want to generate new ECDSA keys (with a maximum length of 512 bits) or ED25519 we will have to enter the following commands:

ssh-keygen -f /etc/ssh/ssh_host_ecdsa_key -t ecdsa -b 521
ssh-keygen -f /etc/ssh/ssh_host_ed25519_key -t ed25519

Authentication in SSH: All modes explained in detail

In this section we are going to show you the different authentication methods that we have available on the server. Normally we have two methods mainly: username and password (something we know), and also with cryptographic keys (something we have). However, we can provide the system with additional security, combining these authentications with, for example, a One Time Password generated by an application such as Google Authenticator or Latch OTP. In addition, we can also provide the Latch system, to prevent any user from logging in if we do not have the “latch” open.

User and password

If we want to enable the login to the service through the system username and password, the configuration file must have this statement:

  • PasswordAuthentication yes

Otherwise, if we want to prevent authentication through username / password, and only allow connections through cryptographic keys, we must indicate no:

  • PasswordAuthentication no

This sentence affects all users of the system. In order not to be left without access to the server, we should make sure that the PubkeyAuthentication statement is set to “yes”, to allow the login with cryptographic keys.

There is another sentence related to this called ChallengeResponseAuthentication , if we set the configuration to “no”, it will not allow connections where the keyboard is interacted with, so if for example we have a One Time Password configured, we will not be able to log into the system. If we are only going to use cryptographic keys, you can set it to “no” without problems.

SSH public key

To configure public key access to the server, we must set the following statement to “yes”:

  • PubkeyAuthentication yes

This is how we activate the configuration with the SSH public key in the system, however, there are still some steps that we must do so that we can connect to that server, and that is to pass the public key to the computer itself. To do this, we must allow (for now) the authentication with username / password, once we finish all the steps we can deny authentication with username and password without any problem.

From the computer where we want to connect to the server with cryptographic keys, we must create these keys and pass them on to the server. To create RSA keys of 4096 bits we have to put the following command in the SSH client:

ssh-keygen -t rsa -b 4096

In the wizard for generating these keys, it will tell us if we want to save them in /home/usuario/.ssh/id_rsa, we say yes. Subsequently, it will allow us to put a pass-through password to the private key, in this way, if we lose the private key, nothing will happen because they will not be able to connect, since it is always necessary to enter a pass-word to be able to make the connection correctly.

Once we have created the public and private key on our computer, we must send the public key to the SSH server where we want to connect, be careful: the public key.

ssh-copy-id usuario@IP_servidor

Automatically the public key will be copied to said server, and we will be able to enable authentication with only public key and we will have automatically registered. The output offered by this command should look something like this:

The authenticity of host '12.34.56.78 (12.34.56.78)' can't be established.
RSA key fingerprint is b1:2d:33:67:ce:35:4d:5f:f3:a8:cd:c0:c4:48:86:12.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '12.34.56.78' (RSA) to the list of known hosts.
user@12.34.56.78's password:
Now try logging into the machine, with "ssh 'user@12.34.56.78'", and check in:
~/.ssh/authorized_keys
to make sure we haven't added extra keys that you weren't expecting.

In this output, the user must confirm that they want to add the identity and enter the login credentials for the account that they want to use in that service. For this reason it is important that we still maintain the possibility of authenticating with username / password on the server. Once this process is completed, we should be able to log in to this computer without entering the password:

ssh usuario@IP

Remember to set the “PasswordAuthentication no” directive to not allow access via username and password.

Username and password with One Time Password (Google Authenticator or Latch OTP)

In this part of the manual, we are going to authenticate with the usual username / password, but also, we must use an OTP with Google Authenticator or Latch OTP to enter the session. That is, we will provide the SSH server with two-step verification.

The first thing we must do is install a series of dependencies necessary to configure double authentication on our SSH server. To do this we will open a terminal and type:

sudo apt install libpam0g-dev make gcc wget ssh

Once the dependencies are installed in our system, we can download the software for double authentication.

sudo apt install libpam-google-authenticator

We already have Google Authenticator installed in our operating system. The next steps to follow are the configuration of the tool to be able to use it in our SSH.

To start with the configuration of Google Authenticator we simply have to type in the terminal:

google-authenticator

NOTE: Run it without root permissions (sudo), that is, run it as a “normal” user. If you run it as root, that Google Auth will only be available in root itself, and disabling it in SSH itself will do nothing.

Next we will see a simple wizard from the terminal. The first thing it will ask us is if we want our access tokens to be time-based. Next we will see the private key, the verification key and the emergency codes if we do not have our mobile phone at hand. We must keep all this data securely so that we can regain access in case of loss of the authentication key.

Then we tell it to save the changes to the file in our / home folder and it will ask us if we want each token to be used only once, even if that limits a login every 30 seconds. To protect ourselves against possible MITM attacks we select yes. Finally, it will ask us if we want to extend the validity period of each code instead of just 1 minute and 30 seconds (to avoid time synchronization problems). To avoid brute force attacks we can also limit connections to 3 for every 30 seconds.

Scanning the QR code or manually entering the code can be done in programs such as Google Authenticator, Authy, Latch and a long etcetera. We recommend using Google Authenticator or Latch.

The next step we must do is open the “sshd” configuration file to tell it to use this module for the login. For this we can do a “clear” to clear the terminal and type in it:

sudo nano /etc/pam.d/sshd

And we will add the following line to the end of the file:

auth required pam_google_authenticator.so

We save the changes and open the sshd_config file with the following command:

sudo nano /etc/ssh/sshd_config

And we change the line “ChallengeResponseAuthentication no” to “ChallengeResponseAuthentication yes”.

We restart the server with “sudo /etc/init.d/ssh restart” and once it starts again, we will have two-step authentication enabled.

Once done, the login will also ask us for a one-time password, the code generated by our mobile application.

SSH public key with One Time Password (Google Authenticator or Latch OTP)

The configuration at the public key level must be exactly the same as before, and at the installation and configuration level of the Google Authenticator as well. The only difference is that in the sshd_config file we must have something like this:

PasswordAuthentication no
ChallengeResponseAuthentication yes
PubKeyAuthentication yes
UsePAM yes
AuthenticationMethods publickey,keyboard-interactive

And in the file /etc/pam.d/sshd we must have something like this:

#@include common-auth
auth required pam_google_authenticator.so

It is very important to put a pound sign (#) to comment on the @include, in this way, we will authenticate correctly with the public key plus the OTP code generated by the mobile. In this way, we will be telling the server to accept public key authentication only.

Latch configuration in OpenSSH and later choose authentication method

Latch for OpenSSH currently has the limitation that we can only use it for one user, that is, if we are going to try to log into the SSH server with several users, we will not be able to protect our team with Latch because it is limited to only one. We recommend you access the official website of the Latch plugin for Unix on GitHub , there you will find the step-by-step manual to configure it correctly with the SSH service if you are interested. We must remember that it only allows one user to be paired.

Additional security measures: firewall, port-knocking, fail2ban and DenyHosts

In this section we are going to use additional software to protect the SSH server, since it is essential to have additional security. We will use both the firewall based on iptables, as port-knocking to always hide the service behind the firewall, as well as fail2bat and DenyHost to detect possible brute force attacks and stop it with the firewall.

Iptables firewall configuration to protect SSH

The iptables firewall incorporated in most Linux-based systems will allow us to limit the number of simultaneous connections to our server, and also, we will be able to use a special module called “recent” to save all of them in a database. connection attempts, ideal for avoiding brute force attacks.

Limit the number of simultaneous connections in iptables

If an attacker tries to connect multiple times from the same IP, we can limit that number of connections to mitigate his attack. This does not nip a possible attack in the bud, but mitigates it with two objectives: not having a large memory and CPU consumption on the computer by opening multiple SSH connections, delaying a possible brute force attack by opening multiple connections.

This statement ACCEPTS up to 5 connections that come from the same public IP, from the sixth connection we block it. If we have several network interfaces, we must use the «-i» to set the interface for which we are applying this rule, if we do not put anything, it will apply to all of them.

iptables -A INPUT -p tcp --dport 22445 -m connlimit --connlimit-upto 5 --connlimit-mask 32 -j ACCEPT

iptables -A INPUT -j DROP

Configure the recent module to mitigate brute force attacks on the SSH service

The recent module serves to limit the number of connections per second at the IP level, this is ideal to protect us from attacks on the SSH port because an attacker will try multiple passwords. In the following example, we will register all the connections to the destination TCP port 22445 in a database, and we will register the origin of those connections (the public IP of a possible attacker).

Subsequently, we check that there are no more than 4 matches in the table in the last 60 seconds. If there are more than 4 matches, we proceed to block all connections from there.

iptables -A INPUT -p tcp --dport 22445 -m conntrack --ctstate NEW -m recent --set --name ssh --rsource

iptables -A INPUT -p tcp –dport 22445 -m conntrack –ctstate NEW -m recent –rcheck –seconds 60 –hitcount 4 –name ssh –rsource -j DROP

This module differs from the previous one, in that it checks these connections by time. Normally to protect the SSH service it is better to use this recent module than the previous one.

Port-Knocking to “hide” the SSH service

Port knocking is a discreet method of opening ports that the firewall keeps closed by default. It works by requiring attempts to connect to a series of closed predefined ports. When the correct sequence of port “touches” (connection attempts) is received, the firewall then opens a certain port (s). The benefit is that in a normal port scan it would appear that the port service is simply not available.

Port Knocking is an application, which by default is not installed in operating systems, you can install it through the official repositories. In our case, when using Debian 9, the installation would be like this:

sudo apt-get install knockd

Once installed, we must enable it by editing:

sudo nano /etc/default/knockd

And putting: START_KNOCKD = 1

Next, we start the service:

sudo service knockd start

The knockd configuration file is in /etc/knockd.conf

We must edit it with any file editor, necessary root permissions. The file will look like this:

[options] UseSyslog

[openSSH] sequence = 7000,8000,9000
seq_timeout = 5
command = / sbin / iptables -A INPUT -s% IP% -p tcp –dport 22445 -j ACCEPT
tcpflags = syn

[closeSSH] sequence = 9000,8000,7000
seq_timeout = 5
command = / sbin / iptables -D INPUT -s% IP% -p tcp –dport 22445 -j ACCEPT
tcpflags = syn

And in order to “open” the port of the SSH service, we must put in the console “knock IP_address 7000 8000 9000”. Once we have used the service, we can close it with the statement that we have previously put in the configuration file, it does not have to be the other way around (it depends on how you have configured the file above).

Another option that we have in Port Knocking is the temporary unblocking of the server, in this way, we will open the port for 10 seconds (or whatever you want), and that is when we will have to log into the service. Later, the port will be closed and if we are logged in, it will not kick us out of that server.

[options] UseSyslog

[SSH] sequence = 5438,3428,3280,4479
tcpflags = syn
seq_timeout = 15
start_command = / sbin / iptables -A INPUT -s% IP% -p tcp –dport 22445 -j ACCEPT
cmd_timeout = 10
stop_command = / sbin / iptables -D INPUT -s% IP% -p tcp –dport 22445 -j ACCEPT

In this way, when we leave the server, we will not have to “close” the door as in the previous case, since it has only been open for 10 seconds.

Fail2ban to mitigate brute force attacks on SSH

We can also install the fail2ban program to ban IPs that make many unsuccessful connection attempts (that get the password wrong). This program is well known and used, as it is very easy to configure and launch. We can install it by putting

sudo apt install fail2ban

Now we copy the .conf file into the same .local file for this configuration to apply:

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

Now we can create with fail2ban a custom rule for SSH, we create a new configuration file that will be in charge of overwriting the previous main jail.local file.

sudo nano /etc/fail2ban/jail.d/sshjail.local

And we paste this:

[sshd] enabled = true
port = 22445
bantime = 3600
findtime = 600
filter = sshd
maxretry = 3

And we start it, stop and restart it doing as if it were SSH, in this case start = start:

sudo /etc/init.d/fail2ban restart

To see the connection LOGS you will have to look at the /var/log/auth.log path, and to see the fail2ban logs you have to look at them here: /var/log/fail2ban.log

DenyHosts: Like fail2ban but specifically geared towards SSH

We also have another program dedicated exclusively to SSH, it is called DenyHost and it has a large database of IPs known as attackers. It is another solution to possible attacks if we always have our SSH server exposed to the Internet. DenyHosts works the same as fail2ban, it watches the connection logs to detect if we are facing a brute force attack, and it also checks IP databases to detect if they are botnets.

To install this program we will need to do it from the official repositories, we assume that in /etc/apt/source.list:

sudo apt install denyhosts

The first part of the configuration is done in the /etc/hosts.allow path, here we will have to put the white list with our computers so that it never blocks us, this is essential so as not to block ourselves through the firewall, especially if you are using a remote server it is really important to do this step.

sudo nano /etc/hosts.allow

The syntax you should use is the following:

sshd: DIRECCION_IP

For example, with this you would be allowing three source IP addresses:

sshd: 192.168.1.2

sshd: 192.168.1.3

sshd: 192.168.1.4

We save to apply the changes, and now we will have to edit the DenyHosts global configuration file:

sudo nano /etc/denyhosts.conf

In this configuration file we will see commented on the different configuration options available, the syntax is very similar to Fail2ban, so you will not have problems when configuring it.

Pam_tally2: another highly recommended alternative

This tool is also very similar to the previous ones, it performs exactly the same function: manage failed attempts on the SSH server. This program will allow us to count the access attempts of different users with their corresponding source IP addresses, if there are too many failed login attempts, they will automatically be denied access through the firewall. This tool has two parts, the pam_tally2.so which is the PAM module that we can configure in our Linux operating system, and we will also have the pam_tally2 which is the program itself.

Finally, the SSHGuard program is also highly recommended to adequately protect our SSH server from intrusion attempts.

How to check the security of my SSH server

Today we have several tools to check the security of our OpenSSH server that we have just configured, these programs will be in charge of analyzing the server configuration by making connections to the server, in order to detect some type of incorrect or unsafe configuration. Some of the most recommended programs are Rebex SSH Check which is a highly recommended online scanner, in addition, we also have ssh-audit which is a tool that is installed locally where the SSH server is to check the security of the server.

So far we have come with this manual on how to configure the SSH service on our server in detail. If you have any questions you can put a comment and we will respond delightedly.