Notes / Server Setup

(This was originally on my old website, I have resurrected it here.)

Here we do some basic server setup, hardening it in preparation for whatever we want to use it for, in my case, hosting this website.

I am using a DigitalOcean Ubuntu 14.04 instance.


The plan is to disable root login, and only allow login to a new user using ssh keys.

We start with a freshly spun-up droplet.

ssh root@<SERVER_IP>

Create a new user, and add it to the sudo group.

adduser <USERNAME>
gpasswd -a <USERNAME> sudo

Back on our client machine generate an SSH key pair, and upload our public key to the server.

ssh-keygen -t rsa -b 4096
ssh-copy-id <USERNAME>@<SERVER_IP>

Over on the server, in /etc/ssh/sshd_config, we want PermitRootLogin no and PasswordAuthentication no. This will disable logging in as root, and disable logging in using a password (so key only login).

service ssh restart

Now exit and ssh in as the new user.


We will drop all incoming connections except TCP connections for HTTP and HTTPS. SSH will be concealed using SPA (single packet authorisation). As a matter of practice make sure out-of-band management is in place in case you lock yourself out.


Make sure the default policy is to accept before we flush, so we are not kicked off

sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -F

Drop invalid packets

sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

Allow loopback connections

sudo iptables -A INPUT -i lo -j ACCEPT

Allow packets that are part of an established connection, and those that are associated with it

sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

Allow TCP connections to ports 80 and 443

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

Change back to the default drop policy

sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP

Now, iptables rules do not persist restarts, to remedy this

sudo apt-get install iptables-persistent


Next we set up SPA using fwknop. This allows us to send an encrypted packet that is passively sniffed by a daemon running on the server, if we successfully authenticate then a temporary firewall rule is added exposing a service to only our IP for a predefined time period. This obviates the need for tools such as Fail2ban. We will use this to conceal the SSH service.

On the client

sudo apt-get install fwknop-client

We will use AES128-CBC+HMAC-SHA256, since 4096 bit RSA keys are protecting actual login, but if required, fwknop can be configured to use OpenPGP key pairs instead.

Generate the config stanza used when knocking at our server

fwknop -n <NAME> -A tcp/22 -R -D <SERVER_IP> --use-hmac --hmac-digest-type=SHA256 --key-gen --key-len=16 --hmac-key-len=64 --save-rc-stanza

This gets written to ~/.fwknoprc.

When we want to knock do

fwknop -n 

But we still have the server to do, so on the server

sudo apt-get install fwknop-server

Copy thy keys from ~/.fwknoprc on the client into /etc/fwknop/access.conf on the server, and add which port to open

SOURCE              ANY
OPENPORTS           tcp/22
KEY_BASE64          <KEY_BASE64 from client>
HMAC_KEY_BASE64     <HMAC_KEY_BASE64 from client>

Now, fwknop uses timestamps so it is best to keep our server time synced

sudo apt-get install ntp

We can see everything works by knocking from the client then checking an extra rule has been added to iptables

sudo iptables -S


We now have a secure base to build upon, make sure to back up your .ssh, and .fwknop directories. Some further improvements may include using OpenPGP keys for both SSH authentication and SPA, and storing the keys on an OpenPGP card, meaning only pointers to the keys are stored on the client, so we are required to insert the card when we want to login.