Securing a Server

Hint: Tested on Debian 6 and 7, but should also work on Ubuntu server

First steps

Install updates

Make sure our system is up to date.

apt-get update
apt-get upgrade

This and that

First we’ll create a symlink from /bin/sh to /bin/bash

dpkg-reconfigure dash

And select no.

Hostname

We will set the hostname of our system.

vim /etc/hosts

Have your first two lines look like this.

127.0.0.1 localhost.localdomain localhost
192.168.0.100 server1.domain.tld server1

Then also add it to the file /etc/filename then start hostname.sh

echo server1.domain.tld > /etc/hostname
/etc/init.d/hostname.sh start

After that the output of these should be the same

hostname
hostname -f

ntp system clock

To synchronize our system clock via ntp we only have to install ntp and ntpdate

apt-get install ntp ntpdate

Securing your system

Change root password

Change the root password to something long and complex.

passwd

Fail2ban

Fail2ban watches logins and blocks suspicious connections. We won’t need to configure anything it’s awesome out of the box.

apt-get install fail2ban

Creating the login user

Now we will create the user we are going to use to login to our system.

useradd flowerpot
mkdir /home/flowerpot
mkdir /home/flowerpot/.ssh
chmod 700 /home/flowerpot/.ssh

And set a long complicated password.

passwd flowerpot

Grant the new users all sudo permissions.

visudo

And add the line

flowerpot ALL=(ALL) ALL

Public key authentication

Add the public keys you want to grant access to the system.

vim /home/flowerpot/.ssh/authorized_keys

chmod 400 /home/flowerpot/.ssh/authorized_keys
chown flowerpot:flowerpot /home/flowerpot -R

Lock SSH

Turn off root login and only allow key authentication.

vim /etc/ssh/sshd_config

Change the following lines to disable root login and enable only key authentication.

PermitRootLogin no
PasswordAuthentication no

And now to refresh the configuration we made we need to restart the ssh service.

service ssh restart

Notification on login

I like to know when someone connects via ssh to my server so I create a little script that sends me the information I want. I put it in /root/scripts/shell-login.sh

#!/bin/bash
echo "Login auf $(hostname) am $(date +%Y-%m-%d) um $(date +%H:%M)"
echo "Benutzer: $USER"
echo
finger

Now to run the script when a user is logging in put

/root/scripts/shell-login.sh | mailx -s "SSH Login auf IHR-HOSTNAME" user@domain.tld ```

in

/etc/profile

Then the scripts needs to be executable

chmod 755 /root/scripts/shell-login.sh

Get an E-Mail when there is a new security update

There’s a package that tells you when there is a new security update available.

apt-get install apticron

Then add your E-Mail in

/etc/apticron/apticron.conf

Monit

To make sure your services are always running you can use monit.

apt-get install monit

Then make a little change to the config to make monit run as a service

startup = 1

Then we will have to add every service we want to monitor to the monit config.

vim /etc/monit/monitrc

An example config for CPU load, ssh and MySQL monitoring.

set daemon 180
set logfile syslog facility log_daemon
set mailserver localhost
set mail-format { from: user@domain.tld }
set alert user@domain.tld

check system localhost
     if loadavg (5min) > 1 then alert
     if memory usage > 75% then alert
     if cpu usage (user) > 70% then alert
     if cpu usage (system) > 30% then alert
     if cpu usage (wait) > 20% then alert

check process sshd with pidfile /var/run/sshd.pid
     start program    "/etc/init.d/ssh start"
     stop program    "/etc/init.d/ssh stop"
     if failed port 22 protocol ssh then restart
     if 5 restarts within 5 cycles then timeout

check process mysql with pidfile /var/run/mysqld/mysqld.pid database
     start program = "/etc/init.d/mysql start"
     stop program = "/etc/init.d/mysql stop"
     if failed host 127.0.0.1 port 3306 then restart
     if 5 restarts within 5 cycles then timeout

These are just examples, if you need more you will most certainly find it on the internet.

iptables

iptables will be my firewall. Let’s go ahead and create a new iptables file

vim /etc/iptables.test.rules

Now we are going to add some rules

*filter

-A INPUT -i lo -j ACCEPT
-A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT

-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

-A OUTPUT -j ACCEPT

-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT

-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT

-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT

-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

-A INPUT -j REJECT
-A FORWARD -j REJECT

COMMIT

Then we activate these rules

iptables-restore < /etc/iptables.test.rules

Then we can check and see the difference

iptables -L

Add all the ports you need to this and when you are done save like this.

iptables-save > /etc/iptables.up.rules

And to make sure it that it will work after a reboot we create a new file.

vim /etc/network/if-pre-up.d/iptables

And add these lines to it

#!/bin/bash
/sbin/iptables-restore < /etc/iptables.up.rules

Then make it executable

chmod +x /etc/network/if-pre-up.d/iptables

That’s it

If I have some spare time and anyone wants me to, I might make a puppet or ansible cookbook for this