Steps to Securing Your VPS

Steps to Securing Your VPS

Linux VPS servers have their advantages. In fact, Linux VPS are much more secure when compared to other operating systems like Windows because of Linux’s security model (LSM). But they’re not perfect, and definitely not invulnerable. In this post we’ll go over most important steps you can do to secure your VPS and protect it from hackers.

Use a non-root user

First thing I usually do to secure a new VPS instance is to create a new user. I use this user instead of root to log into the VPS and run commands. It's good to avoid using the root user because it has unrestricted access to the machine and can potentially cause serious damage.

Using a non-root user follows the principle of least privilege and adds a layer of protection against intruders looking to gain root access.

Creating a new user

While logged into the VPS as root, create a new user with the following command:

# Choose any username you want
adduser username
passwd username
# Provide some strong password

All commands in this article are for Ubuntu. Other Linux distributions usually have equivalent programs that can do the same thing. If you Google <command> equivalent <distribution> (e.g.: adduser equivalent fedora) you have a good chance of finding what you're looking for.

Test the create user

$ id username
uid=1000(username) gid=1000(username) groups=1000(username)

We'll give this user the ability to run commands as root with sudo since we will need that later in this article. You can accomplish that by adding the user to the sudo group:

# Use your username here
usermod -aG sudo username

-aG stands for append to group. If you run id <user> again you can see sudo has been added to this user's group list.

$ id username
uid=1000(username) gid=1000(username) groups=1000(username),27(sudo)

Setup SSH for the new user

Next step is to add your public key to the user's .ssh folder so you can log in as the user with SSH.

Let's switch to the new user and create a .ssh folder in the user's home directory:

# Switch to the new user
su - username

# Create the SSH folder
mkdir ~/.ssh

SSH is nit-picky about files and folders permissions and it will fail with an error if they are too permissive. Let's change the folder's permission so only this user is allowed to read and write to it:

# Restrict access to this user only
chmod 700 ~/.ssh

In this folder, we'll create a file named authorized_keys which will contain your public key. SSH will look for the key in this file when you connect to the server.

# Create and open the file where SSH will look for your public key
nano ~/.ssh/authorized_keys

The above command will open the file in the nano editor allowing you to paste your public key. Hit CTRL + X to quit, then Y and enter to save.

A quick way to copy the contents of a file in the terminal is to use pbcopy. To copy your public key, navigate to the .ssh folder on your machine and run pbcopy <aside (assuming is the name of your public key file). The public key is then copied to the clipboard and you can paste it anywhere you want.

Confirm the key is saved by running cat ~/.ssh/authorized_keys. This will print the contents of the file to the terminal and you should see your public key.

Let's change the permissions of this file as well:

# Restrict access to this user only
chmod 600 ~/.ssh/authorized_keys

Open a second terminal session and confirm you can SSH into the server with ssh <user>@<server_ip>. If you've followed the above steps correctly, you should see the Ubuntu welcome message.

Close the first terminal session by running exit twice and proceed to the next section.

Disable password and root login

A private/public key pair has many more bits of data making them impossible to guess in within the human lifespan.

It's good practice to disable password login and protect your VPS from these type of attacks. It also gives you peace of mind that, unless an attacker gets a hold of your private key, the only person who will have access to the server is you.

While we're at it, we will also disable logging in as root since we will not be using it anymore.

Both settings are in a global SSH configuration file. Changing this file requires you to use sudo which will ask you for a password. This is the same password you chose when you created the user.

# Open the SSH config file in the `nano` editor
sudo nano /etc/ssh/sshd_config

Scroll down until you find PermitRootLogin and change its value to no. Do the same for PasswordAuthentication. Make sure they're not commented out by removing any leading # (e.g.: #PasswordAuthentication). Press CTRL + X to quit, then Y and enter to save.

Finally, you need to restart the SSH service for the changes to take effect:

# Restart the SSH service
sudo systemctl reload sshd

Verify that root and password login are disabled by trying to log in as the root user ssh root@<server_ip>. You should see Permission denied (publickey). printed in the terminal.

Block incoming traffic on non-public ports

Using a firewall to close all ports, except those that need to be public, is an essential part of server security. Every application running on a machine is a potential vulnerability that can be exploited by an intruder.

Fewer exposed applications means a smaller attack surface resulting in a more secure server.

A firewall consists of a set of rules. Each rule serves as a filter for incoming/outgoing traffic deciding whether a package is allowed to continue to its destination or not.

We'll use UFW (Uncomplicated FireWall) to create firewall rules. UFW is an easy-to-use program built on top of iptables — the traditional and more difficult interface for configuring firewall rules. UFW comes pre-installed on Ubuntu.

For most newly-created VPS instances, we want to begin by opening up three ports: 22 for SSH, 80 for HTTP traffic and 443 for HTTPS traffic. You can open a specific port or you can specify a service name that is mapped to a port. In the examples below we use service names. sudo ufw allow http is the same as sudo ufw allow 80/tcp.

# Allow SSH connections
sudo ufw allow ssh

# Allow HTTP traffic
sudo ufw allow http

# Allow HTTPS traffic
sudo ufw allow https

You will see two rules added after each command, one for IPv4 and another for IPv6. The rules don't go into effect until we enable the firewall:

# Enable firewall
sudo ufw enable

You will get a warning that enabling the firewall might close the active SSH connection. We've added a rule for SSH so we don't have to worry about that. Type y followed by enter to proceed.

Let's verify the firewall is up and running:

$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443/tcp                    ALLOW       Anywhere
22/tcp (v6)                ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443/tcp (v6)               ALLOW       Anywhere (v6)

You might add additional services in the future that need to be open to the public. The syntax for exposing a port is: sudo ufw allow <port>/tcp. To close a port, you run: sudo ufw deny <port>/tcp. Changes will take effect immediately without needing to restart the firewall.

Enable automatic security updates

The final step to making the server more secure is to enable automatic security updates. The open-source community frequently releases security updates making sure vulnerabilities are patched soon after they are found. Conducting manual updates regularly is time-consuming and often forgotten.

By automating this process you're making sure the system is up-to-date with the latest security fixes.

Note: Automatic updates are only applied to software installed through the Ubuntu package manager and don't include application-specific dependencies (e.g.: npm dependencies for Node.js). It's good practice to update your app's dependencies from time to time.

Ubuntu comes pre-installed with a package named unattended-upgrades that lets us configure automatic updates. This tool will regularly check if the packages installed on your machine have new releases and install them if needed. You can granularly specify which updates you want to be installed and which ones to skip. We'll turn automatic updates only for security releases to minimise the chance of introducing breaking changes.

The following command enables automatic security updates:

# Enable automatic security updates
sudo dpkg-reconfigure --priority=low unattended-upgrades

You will see an interactive dialog asking if you want to enable automatic updates, select Yes.

This command edits two files:

  • /etc/apt/apt.conf.d/20auto-upgrades (configures when and how the script should run)
  • /etc/apt/apt.conf.d/50unattended-upgrades (configures whether an update should be installed or skipped)

If you want to learn more, visit the automatic security updates documentation on the Ubuntu website.

To verify that automatic updates are enabled:

$ apt-config dump APT::Periodic::Unattended-Upgrade
APT::Periodic::Unattended-Upgrade "1";

The "1" stands for every 1 day. You've now enabled daily automatic security updates for your server and won't have to worry about that anymore

Disable protocol 1

The SSH service works with 2 protocols namely protocol 1 and protocol 2. Protocol 1 has lesser security compared to the other, so it's better to use protocol 2 in your communications.

In order to disable protocol 1, open the sshd_config file with an editor.

nano /etc/ssh/sshd_config

Find the following statement and change to "protocol 2".

# Protocol 2,1

Protocol 2

Restart the SSH service after making changes and save the file.

Service ssh restart

Use non-standard ports for SSH

The default SSH service port is 22, so hackers will check this port before anything else. In some cases, administrators change the SSH port to 2222, but you should know that hackers will surely scan the port 22 and if they get no result, their second choice will be the port 2222. It's better to use the ports with a lot of digits that are not reserved for other services. The best choice is between 10,000 and 65,000, in which most of them are free.

Additional security measures include file auditing, isolated execution environments (with Docker), rate-limiting with fail2ban, and more.