Secure Linux Server
In this post I want to give some tips and hints for securing a linux server. Keep in mind that everybody have a different definition of security and most you will have a different setup. This guide does not replace manual information gathering about how to protect your specific application, because there are no general rules that can be applied to every application.
Getting Started
What you need:
- A linux machine (virtualized or bare metal) with shell access
- some basic knowledge about how to use the terminal
At first we need to connect to our machine using ssh. Then we will secure the ssh access to only login using ssh keys instead of plaintext passwords. Furthermore we will configure ssh to only let certain users log in, because users which only run our application should not be used for logging on.
Basic Setup
Update your system
The first and most important step for keeping your systems safe is to keep them updated, so that is the first thing we are going to do.
$ apt update && apt upgrade -y
Create new user
The first thing we should do is to create a personalized user, because we will disable root login over ssh later in this guide for security reasons. You can do this with Test
$ adduser timo
Add user to group
To allow your newly created user to use the sudo prefix to execute commands as root, you first need to add him to the sudo group:
$ adduser timo sudo
Create ssh key
Following you need your client machine to generate a new ssh key. You can use the Linux bash or shell, the Mac OS X terminal or the Windows subsystem (I personally use Debian, but you can choose whatever you prefer). If you don’t have these options you can generate a new key using the putty keygen, but here we are using the shell. If you are asked in which file you want to save the key, just keep the defaults if you didn’t have one already. If you already have a pair of keys then you should choose a different name to not overwrite them. The default name for most distributions and operating system is id_rsa.
$ ssh-keygen -t rsa -b 4096
After we created a new key we need to transfer it to our server:
$ ssh-copy-id -i /.ssh/id_rsa.pub timo @SERVERIP
After you have entered the password of your new user the key should be transferred to your server.
Check if ssh keys work Before disabling password authentication we should check if ssh-keys are working correctly. For this you can open up a new terminal and try to connect with:
$ ssh timo@SERVERIP
If you are connected without the server asking for a password you setup ssh-keys successful. It may happen, that it does not work and that an error message like access denied (publickey)
appears. Don’t worry we will fix this right away.
Troubleshooting
To do this we need to open up the ssh daemon configuration file which is located at /etc/ssh/
.
$ sudo vim /etc/ssh/sshd_config
You need to search for the following line:
#PubkeyAuthentication no
The line may be commented out or not, if it is you need to remove the hashtag. Now we need to set the variable to yes, so that it looks like this at the end:
PubkeyAuthentication yes
Now we need to restart the ssh daemon to use our edited config.
$ sudo systemctl restart sshd
Now you have to try again and check if it works.
Restricting SSH access
After setting up authentication over ssh keys we need to lock down the ssh daemon. For that we need to edit the sshd_config
once again.
$ sudo vim /etc/ssh/sshd_config
Now we have to change some more parameters:
First of all we will disable password based authentication for the whole system. Find the value PasswordAuthentication no
uncomment it if necessary and set it to no, if it isn’t.
PasswordAuthentication no
Because the root user hold all permissions and can do everything on the system we do not want that user to be able to log on to prevent attacks or misuse. For logging on we created a new personal user before. To disable login of the root user find PermitRootLogin no
uncomment it and set it to no if it isn’t.
Optional Steps Because all users that do not have a ssh key in their directory are unable to authenticate we could just deny them getting logged on at all to minimize attack surface. For that we append a new line at the end of the file:
AllowGroups sudo
In this example I use the sudo group, but feel free to create a new group which will be used only for logon. If you only have one or two users it does not make much sense to use a group or if you do not want to use the sudo group you can also restrict to a user level:
AllowUsers timo
Restart SSH daemon to apply changes With that we have restricted the ssh access a far amount. Now to apply these changes we need to restart the ssh daemon.
$ sudo systemctl restart sshd
Double check in a separate shell window that the access to the system still works before proceeding to the next steps.
Setting up fail2ban (Optional)
Fail2ban is a piece of software that was written in Python and it gives us the possibility to monitor the log files of the ssh daemon and block brute force attacks. Its functions are not only restricted to ssh, they can be used for all kinds of services. For some applications their are already some presets, but you can easily write your own, if you want to. SSH keys are not very likely to be brute forced because it would need a few millions attempts, but technically it is possible, so we want to prevent that. If you have other outside facing application as well I highly recommend using it.
To use the software we first need to install it:
$ sudo apt install fail2ban
After that we need to create our own definition file. In this so called fail file we define which services to monitor and what actions to take, when a brute force is detected:
$ sudo vim /etc/fail2ban/jail.local
Here we add the following lines:
[sshd]
enabled = true
banaction = iptables-multiport
maxretry = 8
findtime = 36000
bantime = 2629746
The maxretry
variable defines how much tries one IP has in a fixed amount of time findtime
before getting banned for a certain amount of time bantime
. All time variables are defined in seconds so in this example a IP with 8 unsuccessful authentications during 10 hours will get banned for a whole month. A month seems to be quite a long time, but because I only use ssh keys it is very unlikely that I will ever will trigger this accidentally and most compromised servers stay the same.
Now we need to enable and start the fail2ban service to make everything work:
sudo systemctl enable fail2ban
sudo systemctl restart fail2ban
Now we are ready to go. Have fun with your server, but always keep an eye on your system, because there is no 100% security and no system is safe.