Installing and Hardening an Ubuntu Server

From Stiles Wiki
Revision as of 19:00, 12 December 2020 by Maxwells (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

This guide will help you install, configure, and secure a golden image for your Ubuntu servers.

Requirements

This guide assumes you know the basics of installing an operating system on a computer.

Installing the Ubuntu Server

This should be a pretty standard answer the questions and follow the directions on screen. If you want a static IP address you can set it here, but I like to set a static address through DHCP instead of on the actual server. I also like to use LVM for the disk set ups.

Update and Configure

After you've finished installing the OS, it's time to connect to the server and begin updates and a base configuration. I connect through SSH, but you can do it the physical box if you want.

Fix Disk Size

I've found that if you don't make any changes to the default disk settings, you fill up the disk very quickly. Let's change that first, we need to resize the logical volume to use all the existing and free space of the volume group.

sudo lvm
lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv
exit

And then, we need to resize the file system to use the new available space in the logical volume. After that's done, we should make sure that it shows the new disk size.

sudo resize2fs /dev/ubuntu-vg/ubuntu-lv
df -h

Update the Server

Next, let's get the latest updates for the server and remove any space wasters.

sudo apt update && sudo apt -y upgrade && sudo apt -y autoremove

Timezone, Charset, Unattended Upgrades

Now we need to configure the timezone and our charset. If you want to enable unattended upgrades, now is a good time to do that as well.

sudo dpkg-reconfigure tzdata && locale-gen en_US.UTF-8 && dpkg-reconfigure locales && dpkg-reconfigure -plow unattended-upgrades

Hostname

Check your hostname to make sure it's set correctly.

hostnamectl

If the previous command returned the wrong hostname, you can run the following command to change it permanently. Change <hostname> to what you want the new hostname to be, without the <>.

sudo hostnamectl set-hostname <hostname>

If you change the hostname, it's a good idea to update the hosts file with the new hostname. /etc/hosts

127.0.0.1 <FQDN> <hostname> localhost
...

Securing the Server

ICMP Requests

Now we can begin securing the server, first we should block ICMP requests. /etc/sysctl.d/50-ip-sec.conf

# Disable Source Routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0 
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0

# Disable acceptance of all ICMP redirected packets on all interfaces
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0 
net.ipv6.conf.default.accept_redirects = 0

# Disable send IPv4 redirect packets
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0

# Set Reverse Path Forwarding to strict mode as defined in RFC 3704
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# Ignore ICMP broadcast requests
net.ipv4.icmp_echo_ignore_broadcasts = 1

# Block pings
net.ipv4.icmp_echo_ignore_all = 1

# Syn flood help
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 5

# Log suspicious martian packets
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians=1
net.ipv4.icmp_ignore_bogus_error_responses = 1

# Disable IPv6 auto config
net.ipv6.conf.default.accept_ra=0
net.ipv6.conf.default.autoconf=0
net.ipv6.conf.all.accept_ra=0
net.ipv6.conf.all.autoconf=0
net.ipv6.conf.eth0.accept_ra=0
net.ipv6.conf.eth0.autoconf=0

# Disable TCP Timestamps
net.ipv4.tcp_timestamps=0

Spoofing Attacks

Next we should block spoofing attacks. /etc/sysctl.conf

...
# Do not accept ICMP redirects (prevent MITM attacks)
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
# _or_
# Accept ICMP redirects only for gateways listed in our default
# gateway list (enabled by default)
net.ipv4.conf.all.secure_redirects = 0
#
# Do not send ICMP redirects (we are not a router)
net.ipv4.conf.all.send_redirects = 0
#
# Do not accept IP source route packets (we are not a router)
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
#
# Log Martian Packets
net.ipv4.conf.all.log_martians = 1
...

Configuring the Firewall

Next we should set up a firewall. Ubuntu comes with UFW, which is what I'll be using. If you're using SSH, make sure to open that port before you enable the firewall.

sudo ufw default deny incoming
sudo ufw allow 22
sudo ufw enable

We can check the status of the firewall, and see what we're allowing through by running the following.

sudo ufw status

Now we'll drop all ICMP connections at the firewall as well. /etc/ufw/before.rules

...
# ok icmp codes for INPUT
-A ufw-before-input -p icmp --icmp-type destination-unreachable -j DROP
-A ufw-before-input -p icmp --icmp-type time-exceeded -j DROP
-A ufw-before-input -p icmp --icmp-type parameter-problem -j DROP
-A ufw-before-input -p icmp --icmp-type echo-request -j DROP
...

Installing Fail2Ban

We'll want to set up a way to ban IP addresses that attempt to connect to your server but fail repeatedly.

sudo apt install fail2ban

The default settings work for most set ups, but make any changes you feel necessary. Run the following to see who is currently blocked.

sudo fail2ban-client status
sudo fail2ban-client status sshd

Securing SSH

Creating a RSA Key Pair

I use an RSA key pair to connect to my servers through SSH. If you’ve never set up a RSA key pair, continue from here. If you have, skip ahead to copy the RSA key. On the machine you connect from, run the following to generate an RSA key pair.

ssh-keygen -b 4096

Copy the Key to the Server

Next we need to copy the pubic key to the server. I like to use ssh-copy-id if it's available, but that won't be possible through PowerShell if you're using Windows. Bash/Terminal

ssh-copy-id <username>@<hostname_or_ip_address>

Windows Powershell

cat ~/.ssh/id_rsa.pub | ssh <username>@<hostname_or_ip_address> "mkdir -p ~/.ssh && touch ~/.ssh/authorized_keys && chmod -R go= ~/.ssh && cat >> ~/.ssh/authorized_keys"

You should now be able to connect to your server with your key.

Disable Password Authentication

You should now be able to ssh into your server without being prompted for your password. If you set up a passphrase for your key, you will be prompted for it. We now should disable password authentication for ssh entirely. Locate the following line and change it. /etc/ssh/sshd_config

...
PasswordAuthentication no
...

All that's left is to restart the SSH service. Please note that you will be disconnected if you are currently connected to your server over ssh.

sudo systemctl restart ssh

I know that it’s also a good idea to change the default port that ssh runs on, but I don’t since I don’t let that port talk to anything outside my network. You can if you want though. I also like to restart a fresh server after this whole process, but that's not always necessary.