Here we are again after my last security post about disabling root account on Ubuntu / Debian. This time I will bring you how I chose to implement some security best practice with OpenSSH on some machines I run with Linux based OS like Ubuntu, but works even with other Debian based distro.
In this guide I will try to explain how to secure a machine service widely used called OpenSSH from malicious attacks. They are usually performed using some vulnerabilities of a non proper configured system leaving your server or pc available to possible hacks.
What is OpenSSH?
OpenSSH or more simply ssh (secure socket shell) is a service hosted by a machine (server or host) which allow another PC (client) to connect to its shell.
This service is by default listening for connections on port 22 of the host.
The communication is encrypted by the service securing all the information will be exchanged.
As a default service on a machine, this service will be already there waiting for someone to connect to it , even if you are never going to use it.
Ssh default configuration usually have a basic security setting provided by the OS you’re going to use or your host provider, that’s why one of the firsts steps is to secure ssh connections.
Next you will find some tips on hardening your ssh service.
You may follow all of them or only some, this depend on much the services you are hosting are exposed to the web pirates.
How do I configure my SSH?
Your OpenSSH server side service will be running in the system under the name of “sshd” and in can be configured customizing your rules inside a text file.
Let’s open it:
$ sudo nano /etc/ssh/sshd_config
In this file are going to be housed all the rules for the sshd (sshd_config is the server, ssh_config is for the client). Here you may find the active rules, and the rules wich are not active with a “#” at the beginning. I encourage you to spend some time exploring what is already inside.
Remember to save the changes you’re going to make and try to double check always what are you doing. If you are away from the machine or you don’t have other way to access the machine you are possibly going to lock out yourself.
NOTE: after every change you are going to make to sshd_config file the sshd service has to be restarted:
$ sudo service sshd restart
I am not responsible for any damages you’re going to make using the information in this article, here you will find knowledges whit the only purpose to show you how ssh service security can be hardened.
1. Disallow root login.
WARNING: before performing this step be sure you’re not actually logged in as the root user and to be executing this steps as a sudo user.
If you’re not sure how to do it check in this guide: Disabling root account on Ubuntu / Debian
By default the root user is able to access your system and this is the main target for wide ranges attacks. It’s evident how important is to avoid a possible login from a user with such powers.
Now add to it on a empty row (I usually prefer at the beginning of the file):
PermitRootLogin no
If you can’t avoid to use the “root” user jump this step and focus on next points to secure ssh at best your machine.
Restrict access to specific users
If we know the specific users will be using ssh service we can limit the access only to those.
We can do that adding/editing the row:
AllowUsers Walter.W Jessie.P Saul.G
If we need to specify for a user a specific IP from where he should be connecting we can add him this way:
AllowUsers [email protected] [email protected]
Same we can do to deny the access to certain users this time with the rule:
DenyUsers Hector.S Tuco.S Todd.A
Restrict access to specific IPs
As before we can parse a list of IPs to our sshd service from which we grant the access to our machine.
We can do this adding to our sshd_config the rule:
ListenAddress 192.168.1.159 2001:0620::0211:24FF:FE80:C12C pollos.hermanos.net
Before saving and restarting the service be sure the machine is reading your IP properly, if you are in another network it may be seen different.
Change service port
Since the standard port of the ssh service is always by default the number 22 we should consider to change it in order to secure ssh attacks from bots looking for system listening on that port.
First we should ensure to choose a port number that is not in use and that will not be used in the future and its number is between 1024 or 65535.
When ready add this row to your file:
Port 52022
Disable empty passwords
By default the system allow users to set empty password for their accounts.
This is very unsafe and you can secure ssh to reject login from a user who has an empty password:
PermitEmptyPasswords no
By default on many rules the value is already “no” (disabled) but is better to have it written. Just to be sure. XD
Disable host-based authentication
This authentication method gives you a way to login into a machine automatically thanks to a previous setup on both host and client o a key.
Since this method is more likely set up when you’re going to work with a pool of machines we are going to disabilitate it:
HostbasedAuthentication no
TCP wrapping
Even if it’s called wrapping actually we are not really going to do that but what this method does is to perform a check on the incoming connections and see if they match our configuration.
So when a connection want to be established first goes through the service TCP-wrapper (libwrap). This daemon is going to compare the origin of the connections with this files:
/etc/host.allow
/etc/host.deny
The program is going through the files in this order.
If there’s a match then the connection will be accepted or dropped.
This depend usually by which file (.allow or .deny) the match will be found.
If no match is found by default the connection is allowed.
This instrument is perfect to secure ssh in combination with a firewall since a firewall can’t examine what is inside encrypted connections.
This argument is pretty wide with lots of capabilities and we can’t get in deep here in this article, maybe in a future article.
I will add an example of what you can do with a basic approach:
#
# /etc/host.allow
#
# allow all connection from my network or localhost
ALL : 192.168.10.0/255.255.255.0 localhost
# allow connection to this services from everywhere
ipop3d imapd sshd1 : ALL
# allow connection from host
sshd2 : david.v1t.it
and usually in the .deny file you will just go for denying everything else:
#
# /etc/host.deny
#
ALL : ALL
Set time limit to login attempts
When we are trying to login we have plenty of time to insert username and password but we can and we must shorter this time to avoid possible attacks to have to much time to be there and try to test our system.
We can add to our configuration file the line:
LoginGraceTime 60
Shorter is better.
Set time limit to sessions
The ssh connection between client and server after is established remain open until one of the two decide to close it or the connection will fall.
This can give the opportunity to others to get to your computer when you’re not there if you usually leave it unprotected and do what they want. Plus the connection not properly closed may remain alive and keep busy some system resources. At this point we can add rules to check the session inactivity and close the connection from server side.
This system is based on making a certain amount of checks every x seconds and after they will result all in an inactive state to close the connection.
To setup the time between one check an the other we have to add the following parameter:
ClientAliveInterval 60
and then the counter after how many times the check has failed before closing the connection:
ClientAliveCountMax 60
In this case the system will perform 60 checks with 60 seconds from one to the other:
60 x 60 = 3600 sec => 1 hour
before the connection will be terminated for inactivity.
By default the system use the TCPKeepAlive function to check if the client is still there and close the connection only if a comunication error has occour.
This method, else than the previous we set up wich happend in the encrypted channel, is less secure since this control packet the system send is not encrypted and can be spoofable.
So I usually disable it after I set up the previous method:
TCPKeepAlive no
Customize banner when login ssh
When we try to login we can show the user is trying to login a banner.
Inside this banner we can add different information and one of the best practice is to add information for a possible attacker to scare him away.
Even if this practice isn’t a “official” way to secure ssh is still able to intimidate who is going to attack your system.
We can make it look as a governative device or if we are leading a business out of it consult a lawyer before publishing whatever. Especially if third person are going to use it.
The file you can create it but by default the system has already a file meant for this purpose:
$ sudo nano /etc/issue
To set up the file OpenSSH will be using to print at login we have to add the rule:
Banner /etc/issue
Disable .rhosts login file
In the system, during login attempt, the file ~/.rhosts and ~/.shosts are parsed to check if there’s some host-user combination inside.
If a host-user combination is going to be in this file that match the user trying to login for him it will be granted the access without asking for the password.
Since this practice is really insecure and another user or service can get to edit this files is very suggested to avoid our ssh service to use this function:
IgnoreRhosts yes
Force to use Protocol 2
The new protocol 2 has lots of improvements from the old protocol 1 but still the connection may be performed using the old one.
Today the standard is the 2nd version and is not compatible with the old one.
However giving to the connection a specific parameter the connection can still be performed.
To avoid this possibility we are going to set up the rule in our file which impose to use only the protocol 2 rejecting the old one:
Protocol 2
we can try to connect to the server whit the parameter -1
and check which will be the answer. (remember to save and restart the service before)
$ ssh -1 [email protected]
Limit password attempts
Brute-force attacks are based on trying a huge amount of passwords looking for the good one. To make the life difficult to this attempts we can secure ssh setting up a number of wrong passwords given after which the connection will fall.
We have to set up the rule:
MaxAuthTries 4
When the connection tries will be more than the half of the selected number they will be logged.
This method make the connection fall but a new one can be setup immediately after from the same client.
For a better prevention again this kind of attacks is better to improve a Fail2Ban service in our server.
I don’t use SSH, do I have to do all of this?
No, your best option at this point is to remove the service at all.
Just type this command and confirm:
$ sudo apt purge openssh-server
This command will cancel even all the configurations and dependency.
If you may like to keep them use:
$ sudo apt remove openssh-server
You will always be able to reinstall it through the command:
$ sudo apt install openssh-server
ChallengeResponseAuthentication
This value is on many systems by default “yes” but what does it really mean?
When we start a connection to a ssh server we are prompt for username and passwor. But if I want even other information to grant a user the access?
Basically this rule allows/denies the “keyboard-interactive authentication” (which have to be abilitate trough another rule we are not going to talk here).
In combination with others rules allow the system to challenge the login process asking for other information. Like what?
Like using a two-factor authentication like the one of Google Authenticator, kerberos, RADIUS, ecc.
If you’re not going to have this additional services running now just add to your file:
ChallengeResponseAuthentication no
Avoid X11 connections
Through SSH is even possible to establish a connection with a graphical interface of your server.
If you don’t use this functionality is better to turn it off to avoid a possible weak spot in the future.
You can do this adding to the configuration file the rule:
X11Forwarding no
Testing your configuration
After you have added a rule in your sshd_config file you can’t be there testing all of them if they have been deployed.
Luckily the service has a routine that is going to do this for you.
You can run it with:
$ sudo sshd -t
Con l’opzione -T
you’re going to run the extended one
Other things you can do to secure ssh:
- Use pubblik key authentication instead of password
- Use a service like Fail2Ban to prevent bruteforce attacks
- Limit access only to the user folder to prevent access to root folders
- Implement a 2 factor authentication
- Use keychain authentication (helps to manage the public key auth.)
- Implement a “honeypot”
- Use “port knocking” to abilitate the port only when needed from the outside
If you have request for next security topic just post a comment and I will see to schedule it somewhere.
Next post will be about the project I’m working on in the house of a friend to create a domotic brain with a Raspberry using OpenHab connecting all his lights, curtains and I guess even more. 🙂