Initial VPS Security Setup

When you first purchase a Virtual Private Server (VPS) you have a basic operating system with little to no security precautions other than your root password. There often no firewall, no fail2ban, no filters or security measures of any kind. In fact, some of the software is not up to date and might have vulnerabilities. The longer you leave a VPS live and unsecured the more likely it is someone will hack it.

Yesterday I got a new VPS from Vultr. Here are the first few things I did with that VPS to ensure that it is secure against most hacking attacks.

I chose a minimal Debian installation as my operating system. Even if you chose CentOS or a different Linux distribution the following steps are a useful guide, it's just that the commands might be a bit different.

Update The System

The very first thing is to SSH into the server. Obviously. I do this as root with the random password Vultr gave me when I created this VPS. Once logged in as root the very first thing I do is update the operating system. Debian uses the apt-get command, and I run the following:

apt-get update apt-get upgrade apt-get dist-upgrade

Now all my packages are updated.

Change Root Password

I don't actually know what algorithm the default Vultr root password is created with. It might be something really weak and easy to guess. It's also hard to remember a bunch of random letters, so the next thing I do is change the root password.

[email protected]:~# passwd Enter new UNIX password: Retype new UNIX password: passwd: password updated successfully [email protected]:~#

Bam, easy enough.

Add New User

Using root for your day to day activities on a server is a bad idea. It's best practice to disable SSH access for root user altogether. We'll get to that, but if I want to disable the root user, I need to create a new user who can log into the server.

Add a user called USER:

[email protected]:~# adduser USER perl: warning: Setting locale failed. perl: warning: Please check that your locale settings: LANGUAGE = (unset), LC_ALL = (unset), LANG = "en_US.UTF-8" are supported and installed on your system. perl: warning: Falling back to the standard locale ("C"). Adding user 'USER' ... Adding new group 'USER' (1000) ... Adding new user 'USER' (1000) with group `USER' ... Creating home directory '/home/USER' ... Copying files from '/etc/skel' ... Enter new UNIX password: Retype new UNIX password: passwd: password updated successfully Changing the user information for USER Enter the new value, or press ENTER for the default Full Name []: Room Number []: Work Phone []: Home Phone []: Other []: Is the information correct? [Y/n] Y [email protected]:~#

Two things of note. The full name, room number, etc of the new user do not matter, so I just press ENTER when asked. Also, the above gave a perl warning. It looks like I need to set by locale settings.

To fix the above perl warning edit or create a file called /etc/locale.gen.

Since I am going to be using English and am based in the United States I uncommented the line reading en_US.UTF-8 UTF-8

The final step is to run [email protected]:~# /usr/sbin/locale-gen

The perl warning will now be gone.

Add Sudo To New User

So now there is a user called USER on the server. I can log in using SSH. However, this user does not have sudo privileges, so I cannot run certain commands. I can use su to switch users to the root user, but it's safer to use sudo.

Since this is a minimal installation sudo is actually not installed by default. As the root user I install sudo with: [email protected]:~# apt-get install sudo

Ok, sudo is installed, and now I need to add USER to the sudo group.

[email protected]:~# groups USER USER: USER [email protected]:~# adduser USER sudo Adding user USER' to groupsudo' ... Adding user USER to group sudo Done.

OK, I am finally ready to log out of the VPS as root and log back in as USER. Now USER has sudo privileges and is able to make all the changes I will need to make.

I can log back in and test sudo by running the ls command or just about any other command

[email protected]ev:~# exit Localhost:~$ ssh [email protected] [email protected]'s password: [email protected]:~$ sudo ls [sudo] password for USER: [email protected]:~$

There is nothing in my home directory yet, so the ls command has no output, but I was asked for my password and able to run the command using sudo. If sudo was not working properly I would have received an error.

Install Fail2ban

I have enough experience with leaving servers connected to the Internet to know that any IP address on the Internet will be found and scanned by hackers. They will often try to use a brute-force SSH attack to gain the password to the server. Fail2ban will block these attacks from happening.

sudo apt-get install fail2ban

Change SSH Port

Fail2ban is fine out of the box, but I like to change my SSH port to something different than the standard port 22. To make this change or any other fail2ban edits we make and edit /etc/fail2ban/jail.local.

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

If you want SSH to use a none standard port then find the section on SSH in the above file and change the port = 22 line to some other number.

After making any changes be sure to restart fail2ban.

sudo service fail2ban restart

Not only do you have to change the SSH port in fail2ban, but you have to tell the SSH demon to actually use the new port. Change the port: 22 line in the /etc/ssh/sshd_config file and then restart SSH.

$ sudo vi /etc/ssh/sshd_config port: 12345 $ sudo service ssh restart [ ok ] Restarting OpenBSD Secure Shell server: sshd.

Now when you SSH into the server you will have to specify the port number like this:

ssh [email protected] -p 12345

Disable Root SSH access

While we are on the subject of editing /etc/ssh/sshd_config, this is also where you would disable root SSH access. Find the line PermitRootLogin yes and change it to say PermitRootLogin no, save the file and restart SSH.

Disable SSH Passwords

It is more secure to use a private/public SSH key pair for logging into servers. I wont go into the details of generating public/private keys here, but there are articles that explain how to create, enable and use SSH keys. Once yours keys are setup you can disable SSH passwords.

If you are like me and need to access your VPS from many different locations you can get a little USB drive to carry your private keys on.

Install and Setup UFW

UFW is an easy to use Linux firewall. This will secure unused ports on your server. First, install it:

sudo apt-get install ufw

We can setup our firewall rules before actually activating the firewall. I always disable all ports by default and then add the ports I will need.

sudo ufw default deny incoming sudo ufw default deny outgoing

I want to allow at the very least port 80 for http access since I plan on running a webserver on this server, and I want my changed SSH port to be allowed so I can log into the server. If you ever block your SSH port you might lock yourself out of the server completely and might need to wipe the whole server and start from a clean OS installation. Not fun.

sudo ufw allow 80/tcp sudo ufw allow 12345/tcp

And I want to allow some outgoing ports. Those include ports which the server might need for things like DNS and git. If you do not unblock certain outgoing ports then apt-get updates or installs might not work for example.

sudo ufw allow out 53,80,443/tcp sudo ufw allow out 53,80,443/udp

Then you have to actually enable UFW

sudo ufw enable

Be sure that the SSH port is allowed before enabling UFW or you might lock yourself out of the VPS. If that happens you might have to either console into the VPS, if your VPS provider allows that, or you might have to reinstall the OS and start from scratch.

You can look over your UFW rules by typing sudo ufw status verbose. Mine ended up looking like this:sudo ufw status verbose Status: active Logging: on (low) Default: deny (incoming), deny (outgoing) New profiles: skip To Action From 12345/tcp ALLOW IN Anywhere 80/tcp ALLOW IN Anywhere 9418/tcp ALLOW IN Anywhere 12345/tcp ALLOW IN Anywhere (v6) 80/tcp ALLOW IN Anywhere (v6) 9418/tcp ALLOW IN Anywhere (v6) 53 ALLOW OUT Anywhere 123 ALLOW OUT Anywhere 22 ALLOW OUT Anywhere 21 ALLOW OUT Anywhere 80 ALLOW OUT Anywhere 443 ALLOW OUT Anywhere 53 ALLOW OUT Anywhere (v6) 123 ALLOW OUT Anywhere (v6) 22 ALLOW OUT Anywhere (v6) 21 ALLOW OUT Anywhere (v6) 80 ALLOW OUT Anywhere (v6) 443 ALLOW OUT Anywhere (v6) Things seem to be working fine so far, but remember, if you ever come across a weird issue where some program is not working or having trouble connecting to the Internet, it might be a port that needs to be enabled in your firewall.

Automatic Security Updates

I have no interest in having to log into the server on a regular basis and run a security update. I used to do this with cron jobs, but now I use the unattended-upgrades package.

sudo apt-get install unattended-upgrades apt-listchanges

To activate the updates I simply type

sudo dpkg-reconfigure -plow unattended-upgrades

and I am done.

This seems like a lot and if you often deploy new servers you will want to automate as much of this as possible. For me, I setup a new VPS rarely enough that I don't mind doing it by hand.

These steps do not guarantee a fully secure server. Nothing ever will. But they are the steps I take and they have worked well enough for me so far. None of my servers have ever been hacked or has any security issues.