Linux Harden SSH
SSH is a secure protocol for administering SSH servers and in many circumstances is the primary way of interacting with a Linux server. While SSH is a secure protocol, it still benefits from a hardening procedure which will reduce the attack surface overall and enhance the security around your server.
Don't Put it on the Internet
If this is possible it is one of the easiest and biggest wins. If your server does not need to be directly accessable via SSH from devices over the internet, don't allow it to be. This does not mean you dont allow internet access for the server, just that TCP port 22 wont be accessable from outside the Internet.
If you are not on the same network as your server, and you have no way of remote connectivity to the network your server is on this may not be an option and if that is the case, or if you just want to lock down your server as much as possible (and you should) continue reading on.
Change the Listening Port
By default SSH listens on TCP port 22, and if your server is listening on port 22 directly on the Internet I'm sure if you look in your syslogs you will see a ton of failed login attempts for various users on that port. This is because attackers looking for low hanging fruit scan IP addresses on the internet for ports like TCP 22 and if they find a device that responds they will attempt a small brute force (typically 10-20 password attempts with various users) and move on if they don't get access. Sometimes there will be more persistent attempts as well. To greatly reduce this you can configure ssh you listen on a non standard port, everything will work the same from a usability standpoint however you will need to specify the custom port number when connecting.
To change the port number edit the file
/etc/ssh/sshd_config and find the line toward the top of the file that specifies the port, it will likely be commented out.
And remove the comment and change that to a high port of your choosing
Save the file and reload ssh
$ sudo systemctl reload ssh
and when connecting you will need to specify the port number when connecting
$ ssh -p 47568 myserver
And you will be able to connect.
To streamline this process you can run this 1 liner command that will modify the file and auto reload the SSH service, just make sure to update the port number to what you want.
$ sed -i 's/#Port 22/Port 47568/' /etc/ssh/sshd_config && sudo systemctl reload
Now to be clear, this is NOT true security, this is more of an obscurity situation which is to reduce the number of lazy attackers showing up in our logs that are looking for low hanging fruit, less logs, less easy to see right on the surface that we are running ssh on our box. I would advise doing this if your server is directly on the internet with SSH listening, but not if it is internal only. It is my opinion that the security gained by not putting it on the internet is not worth also changing the port number to something non standard.
Kind of hard to know what is happening without the logs to look through, this in my opinion is very important and should be among the first things enabled. In order to do this again we will modify the
Find the 2 lines in the config, which are typically commented by default
#SyslogFacility AUTH #LogLevel INFO
And remove the comment from both of them and change the
LogLevel to VERBOSE
SyslogFacility AUTH LogLevel VERBOSE
and finally reload the SSH service
$ sudo systemctl reload ssh
And once again for your convenience I have 2 command which accomplish that without needing to search through the file manually
$ sed -i 's/#SyslogFacility AUTH/SyslogFacility AUTH/' /etc/ssh/sshd_config $ sed -i 's/#LogLevel INFO/LogLevel VERBOSE/' /etc/ssh/sshd_config && sudo systemctl reload
What this does is use the AUTH facility to send the logging messages and sets the level to VERBOSE which will include things like failed login attempts which you definitely want to keep a record of. To read more on logging levels you can get more information here.
Do Not Permit Root Login
Best practice dictates that the root user should not even have a password on the system thus being unable to login, and only able to interact with it using the sudo command. In addition the root user should under no circumstances be able to remotely access the system. Even if you do not allow the root account to login I still recommend disabling SSH access so if for some reason root is able to login to the system, they still can not access it remotely.
Again you will need to modify
/etc/ssh/sshd_config and find the following line, which should be commented as shown below.
Remove the comment, and change it to no.
Save the file and reload ssh.
$ sudo systemctl reload ssh
And you guessed it, I have a one liner for this.
$ sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config && sudo systemctl reload
Restrict Login to Specific Users or Groups
Not every use on the system always needs to login via SSH, only administrators should need remote access, and in my opinion only accounts WITHOUT sudo privileges. That would mean that if a user can authenticate to the system, they must then elevate to an admin account with sudo privileges before any configuration can be modified.
You can restrict access to a set of user and/or a set of groups, and they are not mutually exclusive so you can allow 1 or more groups along with 1 or more users.
This configuration typically does not come in the config file by default so I find the easiest way to add the configuration in the file directly, so sorry no one liners on this one. But again you will want to edit
To add a group add the following line
AllowGroups ssh group2
This will allow users that are members of either 'ssh' or 'group2' access to login.
And to allow 1 or multiple single users add the following line
AllowUsers user1 user2
Which allows user1 and user2 to authenticate via SSH.
I would highly advise against allowing individual users even though it is possible, you should really handle that by group so that it is easily identifiable without the configuration file who has the ability to access SSH. For example my standard is to allow the group SSH, with that knowledge I know any user with that group can login via SSH.
This step bleeds into access control overall, only users that need access to your system should have access to your system to begin with, and only those users that need remote access to your system should have remote access to your system, an added but essential layer of security.