Secure Linux Server

Last update

First steps

cover image

TABLE OF CONTENTS
  • System updating
  • Creating non-root user
  • Checking the safety of the current system
  • SSH Keys generation
  • SSH secure configuration
  • Firewall secure configuration
  • Fail2Ban secure configuration
  • Allow access to specific countries based on IPs
  • Summary

Initial Linux installation has a lot of room for hardening against unauthorized access to the system, no matter what distribution you use. After reading this post you will get the knowledge how to secure your server in record time.

All presented commands have to be executed with admin privileges. In most distributions it will be just sudo before the actual command.

 

System updating

 

Make sure you have an up to date system. It's important because it can download available security updates. Additionally we are going to install some security software in the coming steps so the newer repos the better.

apt update
apt upgrade

 

 

Creating non-root user

 

We need a user with admin privileges but on the other hand it can't be the root user. Moreover we are going to block root users from logging through SSH into the server soon. The solution is a new user with sudo privileges.

adduser new_user_name

 

Add the newly created user to sudo group

gpasswd -a new_user_name sudo

 

 

Checking the safety of the current system

 

This is a very important step before going further because you have to be sure about the safety of the current installation. We are going to use the legendary Rkhunter which scans the appropriate parts of the system in the search for rootkits, backdoors and exploits.

apt install rkhunter

 

rkhunter --check

 

The checking will take a while but it's worth it. Input enter when asked to continue the process. At the end it will summarize the status of your system. If it turns out that your system has rootkits please don't disregard this and google its name/file immediately to find out its severity and importance.

 

SSH Keys generation

 

It's a good practice to generate an individual ssh key for every server you have. Get back to the local machine and generate a strong rsa key:

ssh-keygen -t rsa -b 4096

 

Send the new key into the server:

ssh-copy-id user@server

 

To log with specific key use this command:

ssh -i ~/.ssh/specific_ssh_fkey

 

 

SSH secure configuration

 

Back to the server. Open ssh_config file which holds ssh configuration. You should find it in /etc/ssh folder

nano /etc/ssh/sshd_config

 

There is a lot to cover. SSH config shouldn't be too restrictive so set appropriate values according to your needs. The presented config below is secure enough for most of the systems.

 

TIP

There is a cheat cheat available for SSH which can be useful when using SSH protocol.

 

 

Start with changing the default SSH port . It's important because the default 22 port will always be the first attacked by a potential intruder. If you are not sure what ports are already assigned by your system check it in /etc/services.

 Choose any port not yet assigned preferably from private/dynamic group (49152-65535)

Port 49152

 

You should restrict using SSH by the root user. Root is the default user name in most Linux systems with admin privileges. Use the newly created user from point 2 instead as the additional security measure. Not knowing the user name makes it harder to enter into your system.

PermitRootLogin no

 

It's a good idea to make it more restrictive by selectively choosing what users actually can use SSH.

AllowUsers new_user_name

 

Enable logging by the previously created key from the SSH Keys generation paragraph.

PubkeyAuthentication yes

 

You should definitely block the possibility to log into your system by standard password, the only way to connect should be by the key.

PasswordAuthentication no

 

Disable interactive mode to enter passwords. It's not needed when you use key based authentication.

ChallengeResponseAuthentication

 

Disable the possibility to authenticate based on the host method. In general it facilitates logging into the system based on public keys but only users from .rhosts or etc/hosts.equiv files which is considered insecure.

HostbasedAuthentication no

 

Disable rhost authentication which uses rhosts and /etc/hosts.equiv

RhostsAuthentication no

 

Additionally disable altogether .rhost and .shost files usage related to the previously disabled host and rhosts based authentication methods.

IgnoreRhosts yes

 

Take a closer look at the MaxStartups label. It's often neglected but an important configuration because it can reduce severity of DOS attacks to the SSH service. It specifies the maximum concurrent not yet authenticated connections to the SSH service based on probability or direct value. So you can just type i.e 16 and it will drop the next additional tries immediately or use three values separated with semicolon which are translated into start:rate:full and this way you start using probability.

If concurrent number of connections are greater than the start value the server starts dropping the next connection with probability defined in the rate value. When the number of connections reaches the full value the server starts refusing all connections to the SSH daemon. Depending on the size and type of your system you definitely should consider proper values, my proposition is more restrictive than the default one.

MaxStartups 5:50:30

 

Next reduce max authentication tries per connection. The default value 6 is unacceptable. You should only use the key based authentication so it's value should be set to one. If you choose the password authentication, reduce the number to four, that way an unsuccessful  third and fourth will be additionally logged (by default if authentication fails after half the number specified it starts logging it).

MaxAuthTries 1

 

By default SSH can have up to 10 sessions per one network connection which is highly insecure in most cases because a hacker can use other sessions without need to reauthenticate. Notice that allowing multiple sessions means that multiplexing can be used which can be needed in some environments. Good news is that you can reduce it to one and try if everything works as intended, a single session is always enough to use shell at least.

MaxSessions 1

 

There are two important parameters which when set to not improve security but they can disable some of your software as well. For example if you use some database clients which connect to your server by SSH or FTP client using SFTP.


AllowTcpForwarding no
X11Forwarding no

 

 

Firewall secure configuration

 

Before proceeding further please restart the ssh service depending on the used distribution then disconnect and connect again to the server.


service ssh restart

or

systemctl restart sshd

or 

systemctl restart ssh 

 

After restarting you should be connected through the new designated port (different than 22) and it also means that the old one can be blocked. To be sure about what port SSH is run check it by yourself:

lsof -i -n -P

 

Then enable the Linux firewall. 

ufw enable

 

Next allow the new SSH port and deny the old one.


ufw allow new_ssh_port
ufw deny 22

 

If you always use a fixed IP from ISP you can restrict the firewall rules further. Allow SSH connection only from this IP.

sudo ufw allow from xxx.xx.xxx.x to any port new_ssh_port

 

At the end, restart the firewall.

service ufw restart

 

 

Fail2Ban secure configuration

 

Time to install extremely useful software which level up your server security instantly. With proper config it will even double it! Install the fail2ban then start and enable the service.

apt install fail2ban
 service fail2ban start
 service fail2ban enable

 

It's worth mentioning that this tool performs actions based on logs from the various services. The more important logs you store the better. By default it will also filter SSH logs so let's focus on the configuration then.

 

Allow access to specific countries based on IPs

 

Install GeoIP to get access to an extensive database of ip addresses and their locations.

sudo apt install geoip-bin geoip-database

 

 

Then create a script in the geoip bin folder to enable filtering and logging of incoming connections. The most important is the ALLOW_COUNTRIES parameter, put there your allowed locations. The rest of the script is mostly related to logging based on specific scenarios and you can keep it that way.

#!/bin/bash
# License: WTFPL

# UPPERCASE space-separated country codes to ACCEPT
ALLOW_COUNTRIES="IN US"
LOGDENY_FACILITY="authpriv.notice"

if [ $# -ne 1 ]; then
  echo "Usage:  `basename $0` " 1>&2
  exit 0 # return true in case of config issue
fi

if [[ "`echo $1 | grep ':'`" != "" ]] ; then
  COUNTRY=`/usr/bin/geoiplookup6 "$1" | awk -F ": " '{ print $2 }' | awk -F "," '{ print $1 }' | head -n 1`
else
  COUNTRY=`/usr/bin/geoiplookup "$1" | awk -F ": " '{ print $2 }' | awk -F "," '{ print $1 }' | head -n 1`
fi
[[ $COUNTRY = "IP Address not found" || $ALLOW_COUNTRIES =~ $COUNTRY ]] && RESPONSE="ALLOW" || RESPONSE="DENY"

if [[ "$RESPONSE" == "ALLOW" ]] ; then
  logger -p $LOGDENY_FACILITY "$RESPONSE sshd connection from $1 ($COUNTRY)"
  exit 0
else
  logger -p $LOGDENY_FACILITY "$RESPONSE sshd connection from $1 ($COUNTRY)"
  exit 1
fi

 

Remember you make the script executable.

chmod +x /usr/local/bin/ipfilter.sh

 

For now we have only ip filtering done by the geoip. We need to pass its results to ssh service. Go to /etc/hosts.allow and update so it will get the geopip results.

sshd: ALL: spawn /usr/local/bin/ipfilter.sh %a

 

Finally block all the others ips in the /etc/hosts.deny file.

sshd: ALL

 

Summary

 

If you followed all the above recommendations you have a quite secure server at the moment. Yet there are still possible actions you can take to harden it more. For example you can think about a more restrictive config of the recommended values presented above.

Recent posts