Server Hardening
----------------

While the defaults should be secure, there are some simple
administrative actions that will increase your overall security.  None
of these steps are required, but we encourage you to read this
document to see if the enhancements are relevant for your environment.

Tighten PHP configuration
~~~~~~~~~~~~~~~~~~~~~~~~~

Tighten the security of the PHP installation by creating a file
/etc/php5/conf.d/harden.ini with the following content:

[source, sh]
----
user@host:~$ sudo sh -c 'cat > /etc/php5/conf.d/harden.ini'
display_errors = Off
log_errors = On
user@host:~$ 
----

Tighten Apache configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Tighten the security of the Apache installation by making sure
directory listings are disabled globally.  Edit
/etc/apache2/conf.d/security and make sure the following is
uncommented:

[source, xml]
----
<Directory />
  AllowOverride None
  Order Deny,Allow
  Deny from all
</Directory>
----

Time Synchronization
~~~~~~~~~~~~~~~~~~~~

For logging and (on the validation server) time-stamping it is
important to have synchronized clocks.  Install ntp.

[source, sh]
----
user@host:~$ sudo apt-get install ntp
...
----

Firewall
~~~~~~~~

There is no reason why the KSM needs to listen to incoming requests
from the entire Internet, and restricting access to the intended
YK-VAL servers are recommended.

[source, sh]
----
user@ksm:~$ sudo sh -c 'cat > /etc/network/if-pre-up.d/iptables'
#!/bin/sh

# IPv4 firewall:
iptables -F
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -A INPUT -i lo -p all -j ACCEPT
iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp -i eth0 -s 1.2.3.4 --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -i eth0 -s 2.3.4.5 --dport 80 -j ACCEPT
iptables -A INPUT -p tcp -i eth0 -s 2.3.4.5 --dport 443 -j ACCEPT

# IPv6 firewall:
ip6tables -F
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT
ip6tables -A INPUT -i lo -p all -j ACCEPT
ip6tables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
ip6tables -A INPUT -p icmpv6 -j ACCEPT
ip6tables -A INPUT -p tcp -i eth0 -s 2000:1:2::3 --dport 22 -j ACCEPT
ip6tables -A INPUT -p tcp -i eth0 -s 2000:2:3::4 --dport 80 -j ACCEPT
ip6tables -A INPUT -p tcp -i eth0 -s 2000:2:3::4 --dport 443 -j ACCEPT

user@ksm:~$ chmod +x /etc/network/if-pre-up.d/iptables
user@ksm:~$ 
----

Replace 1.2.3.4 (for IPv4) and 2000:1:2::3 (for IPv6) with the address
of the host you want to be able to login from via SSH, and replace
2.3.4.5 (for IPv4) and 2000:2:3::4 (for IPv6) with the address of the
YK-VAL that will be accessing this YK-KSM.  Add more lines for each
validation server and SSH host.

For a validation server, you may want to allow HTTP(S) requests from
anyone, but not anything else.

[source, sh]
----
user@val:~$ sudo sh -c 'cat > /etc/network/if-pre-up.d/iptables'
#!/bin/sh

# IPv4 firewall
iptables -F
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -A INPUT -i lo -p all -j ACCEPT
iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp -i eth0 -s 1.2.3.4 --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -i eth0 --dport 80 -j ACCEPT
iptables -A INPUT -p tcp -i eth0 --dport 443 -j ACCEPT

# IPv6 firewall:
ip6tables -F
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT
ip6tables -A INPUT -i lo -p all -j ACCEPT
ip6tables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
ip6tables -A INPUT -p icmpv6 -j ACCEPT
ip6tables -A INPUT -p tcp -i eth0 -s 2000:1:2::3 --dport 22 -j ACCEPT
ip6tables -A INPUT -p tcp -i eth0 --dport 80 -j ACCEPT
ip6tables -A INPUT -p tcp -i eth0 --dport 443 -j ACCEPT

user@ksm:~$ chmod +x /etc/network/if-pre-up.d/iptables
user@ksm:~$ 
----

Again, replace 1.2.3.4 (for IPv4) and 2000:1:2::3 (for IPv6) with the
address of the host you want to be able to login from via SSH.

If you want to allow SSH and HTTP(S) from everywhere, but nothing
else, try this:

[source, sh]
----
user@val:~$ sudo sh -c 'cat > /etc/network/if-pre-up.d/iptables'
#!/bin/sh

# IPv4 firewall
iptables -F
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -A INPUT -i lo -p all -j ACCEPT
iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp -i eth0 --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -i eth0 --dport 80 -j ACCEPT
iptables -A INPUT -p tcp -i eth0 --dport 443 -j ACCEPT

# IPv6 firewall:
ip6tables -F
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT
ip6tables -A INPUT -i lo -p all -j ACCEPT
ip6tables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
ip6tables -A INPUT -p icmpv6 -j ACCEPT
ip6tables -A INPUT -p tcp -i eth0 --dport 22 -j ACCEPT
ip6tables -A INPUT -p tcp -i eth0 --dport 80 -j ACCEPT
ip6tables -A INPUT -p tcp -i eth0 --dport 443 -j ACCEPT

user@ksm:~$ chmod +x /etc/network/if-pre-up.d/iptables
user@val:~$ 
----

Database Encryption
~~~~~~~~~~~~~~~~~~~

The database contains sensitive information.  If someone is able to
access your machine physically, they may shut it off and steal it with
the goal of reading out the sensitive information.  By encrypting the
disk, you can prevent this.  Note that this does not protect against
an attacker who has physical access to your server and sufficient time
to read out the data from the already running system.

Full disk encryption will give you the highest protection, but
requires that you can enter the disk encryption password on each
power-up.  This can be unpractical when your hosting environment is
remote.

Partial disk encryption allows the operating system to start up, and
enable you to login to the machine remotely to enter the disk
encryption password.  This is less secure than full disk encryption,
because an attacker could physically disconnect your machine, modify
the operating system to send a copy of the password to the attacker,
but may be sufficient if you keep good track of when your machine is
not working properly.

To use partial disk encryption for the database content, we suggest
you install the operating system as normal but create another file
system on an encrypted volume.

If you need swap space, be sure to only put the swap on the encrypted
volume too.  Make sure that the database does not start up
automatically on boot, and also make sure that the system does not
attempt to mount your encrypted partition automatically.

Setup:

[source, sh]
----
user@ksm:~$ sudo apt-get install loop-aes-utils loop-aes-modules-2.6-amd64
...
user@ksm:~$ sudo rmmod loop && sudo modprobe loop
user@ksm:~$ sudo dd if=/dev/zero of=/root/ksm.img bs=1k count=1M
...
user@ksm:~$ sudo losetup -e AES128 /dev/loop0 /root/ksm.img 
Password: 
user@ksm:~$ sudo mkfs.ext2 -q /dev/loop0 
user@ksm:~$ sudo mkdir /ksm
user@ksm:~$ sudo mount /dev/loop0 /ksm
user@ksm:~$ sudo /etc/init.d/postgresql-8.3 stop
...
user@ksm:~$ sudo update-rc.d -f postgresql-8.3 remove
user@ksm:~$ sudo mv /var/lib/postgresql /ksm
user@ksm:~$ sudo ln -s /ksm/postgresql /var/lib/postgresql
user@ksm:~$ sudo sh -c 'cat > /usr/local/sbin/ykksm-start'
#!/bin/sh
set -e
set -x
losetup -e AES128 /dev/loop0 /root/ksm.img
fsck /dev/loop0
mount /dev/loop0  /ksm/
/etc/init.d/postgresql-8.3 start
user@ksm:~$ sudo sh -c 'cat > /usr/local/sbin/ykksm-stop'
#!/bin/sh
set -e
set -x
/etc/init.d/postgresql-8.3 stop
umount /ksm
losetup -d /dev/loop0
user@ksm:~$ sudo chmod +x /usr/local/sbin/ykksm-{start,stop}
----

Slightly adapted for MySQL:

[source, sh]
----
user@ksm:~$ sudo apt-get install loop-aes-utils loop-aes-modules-2.6-686
...
user@ksm:~$ sudo rmmod loop && sudo modprobe loop
user@ksm:~$ sudo dd if=/dev/zero of=/root/ksm.img bs=1k count=1M
...
user@ksm:~$ sudo losetup -e AES128 /dev/loop0 /root/ksm.img 
Password: 
user@ksm:~$ sudo mkfs.ext2 -q /dev/loop0 
user@ksm:~$ sudo mkdir /ksm
user@ksm:~$ sudo mount /dev/loop0 /ksm
user@ksm:~$ sudo /etc/init.d/mysql stop
user@ksm:~$ sudo update-rc.d -f mysql remove
user@ksm:~$ sudo mv /var/lib/mysql /ksm
user@ksm:~$ sudo ln -s /ksm/mysql /var/lib/mysql
user@ksm:~$ sudo sh -c 'cat > /usr/local/sbin/ykksm-start'
#!/bin/sh
set -e
set -x
losetup -e AES128 /dev/loop0 /root/ksm.img
fsck /dev/loop0
mount /dev/loop0  /ksm/
/etc/init.d/mysql start
user@ksm:~$ sudo sh -c 'cat > /usr/local/sbin/ykksm-stop'
#!/bin/sh
set -e
set -x
/etc/init.d/mysql stop
umount /ksm
losetup -d /dev/loop0
user@ksm:~$ sudo chmod +x /usr/local/sbin/ykksm-{start,stop}
----

Then in the future, to start the YK-KSM, you will need to login to the
machine and issue the command 'sudo ykksm-start' and enter the disk
encryption password.

Again, make sure that you don't use any unencrypted swap.

Intrusion Detection
~~~~~~~~~~~~~~~~~~~

To make some attacks discussed in the previous section harder, make
sure that your system has a hardware intrusion detection system and
that your software is notified when it is triggered.  When the
intrusion detection is triggered, you should stop the database and
unmount the encrypted volume and send out a signal to your
administrators.
