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.
root@dev:~# passwd
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
root@dev:~#
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:
root@dev:~# 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
root@dev:~#
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 readingen_US.UTF-8 UTF-8
The final step is to runroot@dev:~# /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:root@dev:~# apt-get install sudo
Ok, sudo is installed, and now I need to add USER to the sudo group.
root@dev:~# groups USER
USER: USER
root@dev:~# 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
root@dev:~# exit
Localhost:~$ ssh USER@dev
USER@dev's password:
USER@dev:~$ sudo ls
[sudo] password for USER:
USER@dev:~$
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 USER@dev -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
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.
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)
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.