Securing a Linux server
Added 11/09/2024 • Modified 13/09/2024In this howto I will show some practices and methods I have used to secure a new Linux server. The purpose of the server in this case doesn't matter, as these are very general and applicable to almost any Linux server (particularly those running Debian-based distributions). These might not be security recommendations or best practices, and they are not updated regularly. I'm showing what I have done in the past, and taking notes for myself for the future.
Links to all the software and documentation used are included in the end of this howto.
Permissions
Depending on the setup, you might already have superuser priviledges to your system. If not, you can get them by logging in as root user, and adding your own user to the sudo
-group.
To add a user to the sudo group, use command usermod -aG sudo <your user>
. After running the command, system restart might be required. (Can be done with reboot
)
SSH
Usually the first thing I do when I set up a new server is configuring SSH. I make sure to include my public key to .ssh/authorized_hosts
-file,
and then proceed to edit the /etc/ssh/sshd_config
file. In the sshd config I think it is good to set at least these options: PasswordAuthentication no
, PermitRootLogin no
,
PubkeyAuthentication yes
and AllowUsers <your user>
. With these options, root login via SSH is disabled, while only allowing your own user to login. Authentication via password is completely disabled,
and public key authentication is enabled. If no additional changes are made, public key authentication becomes the only accepted authentication method.
After making the changes, SSH server needs to be restarted with the command sudo systemctl restart ssh
. After this, test your setup by logging out (logout
) and connect back to the server. If you are unsure, it might be a
good practice to first test with PasswordAuthentication yes
, and after you see that public key works, disabling the password authentication completely. This way you can avoid locking yourself out of the server :-)
ufw
ufw (Uncomplicated Firewall) is a handy tool, when you want to get started with a firewall for your server easily. With ufw, we can use simple commands to allow ports etc.
To install ufw, just do sudo apt update
and sudo apt install ufw
. After installation, we should first allow at the very least the access to our server via SSH. This is done by adding an allow rule to port 22 (by default).
The rule that allows this can be added by executing the command sudo ufw allow 22
. Please also notice that this rule allows access to port 22 from everywhere (that is, from any IP address). Allowing access from a certain IP address or range
has to be done in a different way than is shown here.
Now that the SSH connection is allowed through the firewall, it's time to enable it. Run sudo ufw enable
to enable the firewall. This command should enable the ufw
service, so that it is started at startup, and start the firewall now.
To confirm that the results were as expected, we can run the command sudo ufw status
, which should tell that the firewall is active and port 22 is allowed through. Now, access to different ports from any IP can be granted with the same command as above.
fail2ban
Now that we have an SSH port wide open for the whole world to see, we might attract some unwanted attention. Allthough from the SSH setup we have the public key authentication enabled, it is still needed to protect our SSH server from things like DDOS and nasty bots which
are scanning the internet for open ports and just spamming login attempts. To prevent these kind of things, we can use fail2ban. It is a free, open-source tool, that reads the system's authentication logs and bans all IP addresses that are causing too many failed login attempts -
just what we need! Install fail2ban with sudo apt install fail2ban
. Next, we must configure fail2ban to spot the incorrect login attempts in our SSH port. We can do this by creating the file /etc/fail2ban/jail.local
.
In that file, we store the configuration for our SSH port, but also for the whole fail2ban program. The configuration goes as follows:
[DEFAULT]
backend = systemd
[sshd]
enabled = true
In this config, we tell fail2ban to use the systemd journal to retrieve the information about failed login attempts, and then just enable the protection for SSH. Next, we should enable fail2ban by running sudo systemctl enable fail2ban
, so that it starts at system startup.
After enabling, we start it by running sudo systemctl start fail2ban
. If the service doesn't start, you might need to install the package python3-systemd
, or fix any errors in the configuration file. Use sudo journalctl -xeu fail2ban
to
find out the source of the problem.
With the configuration file we created, we can use the wide feature set provided by fail2ban. We can determine things like how long a certain IP address is banned with bantime = x
, where x
can be for example 1d
for one day of ban time. By default
bantime
is set in seconds, but you can also use characters like h
for hour or w
for week. We can also determine the time period during which the failed authentication attempts need to happen for the IP to get banned. This can be set with findtime = x
.
Finally, as the last example, we can also set the maximum tries each IP address gets before getting banned, which can be set with the option maxretry
. Usually, these options are set inside of the [DEFAULT]
-block, but you can declare individual rules for
different services (under a different set of square-bracketed lines, for example [sshd] for SSH).
With fail2ban enabled and running, we can now use the fail2ban-client to get information about the status of the system. Use the command sudo fail2ban-client status
to view the overall status of all services protected by fail2ban (also "jails"), and the command
sudo fail2ban-client status sshd
to retrieve information about a single service, in this case the SSH server. Sometimes it might also be helpful to view the configuration that fail2ban is currently using. This can be viewed with sudo fail2ban -d
.
Automatic software updates
Enabling automatic software updates for the server is a critical part in keeping it secure. It is extremely important that especially the software you expose directly to internet (for example, SSH here) gets at least the latest security patches.
Besides, enabling automatic updates with unattended-upgrades
is a very easy task to perform.
You need to do the following:
Run sudo apt update
and sudo apt install unattended-upgrades
to first update the package cache, and then install the unattended-upgrades
-package, that will handle updating our software for us.
Next, we need to check the configuration and enable the unattended-upgrades
-service. The configuration can be checked by opening the file /etc/apt/apt.conf.d/50unattended-upgrades
, and seeing, that the following lines are uncommented:
"origin=Debian,codename=${distro_codename},label=Debian";
"origin=Debian,codename=${distro_codename},label=Debian-Security";
"origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
In this file you can also define other additional update options, or even blacklist certain packages from being updated automatically, see the comments in the file.
Now that the configuration in OK, we just need to enable the unattended-upgrades
-service and start it. This can be of course done with the commands sudo systemctl enable unattended-upgrades
and sudo systemctl start unattended-upgrades
Other systemctl
-commands work also, if you ever need to stop, restart or disable the service.