blowstack logo

Secure Linux Server

First steps

Last update

20 min.
  1. System updating
  2. Creating non-root user
  3. Checking the safety of the current system
  4. SSH Keys generation
  5. SSH secure configuration
  6. Firewall secure configuration
  7. Fail2Ban secure configuration
  8. Allow access to specific countries based on IPs
  9. Summary

 

Initial Linux installation has a lot of room for hardening against an unauthorised 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 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 comming 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 user to log 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 very important step before going further because you have to be sure about the safety of the current installation. We are going to use legendary Rkhunter which scans the appropriate parts of the system in the search for rootkits, backdoors and exploits.

apt install rkhunter

 

rkhunter --check

 

The checkng will take a while but it's worth to do it. Input enter when asked to continue the process. At the end it will summarise the status of your system. If it turned out that your system has rootkits please don't disregard this and google it name/file immediately to find out it's 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 commnad:

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 restrtictive so set appropriate values aacording 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 usefull when using SSH protocole.

 

 

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

 Choose any port not yet assigned preferebly 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 the point 2 instead as the additonal security measure. Not knowing the user name make 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 point 4.

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 authenication.

ChallengeResponseAuthentication

 

Disable the possibility to authenticate based on 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 considererd insecure. 

HostbasedAuthentication no

 

Disable rhost authentiacation 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 authentiaction methods.

IgnoreRhosts yes

 

Take a closer look at MaxStartups label. It's often neglected but important configuration because 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 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 conenctions are greater than the start value the server start dropping next connection with probability defined in the rate value. When number of connections reached the full value the server starts refusing all connections to the SSH deamon. Depending on the size and type of your system you definently should consider proper values, my proposition is more restrictive than the default one.

MaxStartups 5:50:30

 

Next reduce max authentiaction 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 chose the password authentication reduce the number to four, that way an unsuccessfull  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 is some environments. Good news is that you can reduce it to one and try if everything works as indeded, single sessiosn is always enough to use shell at least.

MaxSessions 1

 

There are two important parameters which when set to no improve security but they can disable some of your software as well. For example if you use some database clients which connects to your server by SSH orf 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 than 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 usefull 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 to mention that this tool perform 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 extensive database of ip address and their loactions

sudo apt install geoip-bin geoip-database

 

 

Then create a script in the geoip bin folder to enable filtering and logging of incomming connections. The most important is 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 it's 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

 

Finaly 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 more restrictive config of the recommended values presented above.

 

Recent posts

BlowStack 2021
Portfolio Cheat
sheets