TL;DR - This post is about setting up a VPS the right way - basically it could very well be titled "How to Prevent your VPS from getting p*wned". It covers the basics and is very beginner friendly.
Here we go
So, you've decided on a cloud hosting provider and are about to fire up that shiny new VPS with your favourite flavour of Linux on it? Great! You've come to the right place. While cloud hosting providers have taken every possible step to make the process of spinning up a Virtual Server quick and safe, there are a few steps that you need to take in order to get the most out of your machine - the key words there being "your machine". Why? - because this post is going to tell you how to keep it that way!
When does your machine really stop being your machine? The way I see it, when anyone other than you can successfully give your machine commands - it is no longer your machine anymore.
Now if you're thinking I'm being paranoid consider this: The moment you spin up your virtual instance and get a public IP, you're usually discovered in a matter of minutes by the bots. Who are the bots?
It's a very valid question - especially if you've never taken a peek at what's going on behind the scenes. Bots are basically scripts that are hard at work discovering and p*wning anything that comes alive on the internet. To simplify the matter, they work like this - they scan the internet for live hosts, once a live host is found, it is port scanned and services are profiled. If any service has a known vulnerability, it is usually exploited without much delay. Services without vulnerabilities are then subject to an onslaught of bruteforce attacks. All this happens usually anywhere between 1 to 10 minutes of setting your server up. So time is of essence - let's get into it without further ado.
The Operating System
Before we get into the specifics of what you should do with your cloud server, let's talk about choices of operating system. The question you should really ask yourself is what do you really need? Getting the latest Ubuntu server with all the bells and whistles pre-installed may seem like a convenient option, and it is.....but - and that's a big but - remember that the more stuff you have installed on a system, the wider your attack surface is. Systems with minimal software on board are much harder to exploit, because of a very narrow attack surface. When a hacker gains access to a system, they usually pray for a variety of tools on board so they can 'live off the land'. Rather than upload foreign tools which may trigger defense systems, it's always best for a hacker to use existing tools on the system. Anything that you have can be used against you. From an installation of python which you don't really need, to netcat - these are just two simple examples of common tools, found on most systems which can be heavily weaponized. So choose your operating system wisely - my advice here is to start with as little as possible, a stripped down version of your favourite flavour of Linux.
Since this is a remote virtual private server, it's safe to assume that SSH is the primary means through which you will be accessing your server. Different hosting providers have different methods of setting this up. GCP for example will let you SSH in through a web browser based terminal, or alternatively add your SSH public key to the 'Compute Instance' (that's the term they use for a Virtual Private Server). Other hosts will provide you with a SSH password of a sudo user, or of the root user. The methods of obtaining SSH access are many - each cloud provider has their own quirks and all are quite effective. The question is - what do you do after you get this access?
Let me first begin with a gentle warning- you are probably sitting at home or in your office, and your VPS is in a server room underground at the other end of the planet. Messing up the sshd_config can lock you out of your system. Depending on your hosting provider, this can be anywhere from mildly inconvenient, to having to get in touch with their tech support in order to get back into your system. So be careful. Keep the procedure to recover ssh access handy just in case - however if you get it right, nothing will go wrong. There are many steps to secure your SSH service, let's take a look at a few below
Do away with passwords
The first thing you'll want to do is disable password access and use 'keys' to access your system. Why? An average VPS on the internet (running very normal services - nothing large scale) is attacked an average of 1000 times per day using brute force password guessing. Unless you have a very strong password and hard to guess username, passwords are not a good option. Using SSH keys is a much more secure option and brute forcing the keyspace is much more difficult, and impossible in most cases. So let's get the SSH keys working.
Most systems come with a tool to generate these keys. If you're curious about ssh keys, read about them on ssh.com/ssh/keygen Keep in mind that you'll want to run these commands on your local system and NOT your remote server.
Follow the interactive session and you should end up with a key-pair. The passphrase is optional - for now, don't apply a passphrase. Keep in mind that the defaults will give you a 2048 bit RSA key. This should be sufficient for most purposes, however in case you want that extra security, you can use the following command to give you a 4096 bit keypair.
$ ssh-keygen -t rsa -b 4096
By now you should have your shiny new ssh keypair located in the ~/.ssh directory. In that directory you should see an id_rsa and an id_rsa.pub file(or something of the sort). Now it works like this - you need to get the id_rsa.pub (public key) file onto your remote VPS server. Once it's in the right place there, you should be able to log in using your private key. Let's get this done.
ssh-copy-id -i ~/.ssh/id_rsa.pub user
If there are issues, you can manually add the public key to your VPS. In order to do that, login to your VPS, go to the ~/.ssh directory (in your home folder) and create a file called 'authorized_keys' with only read-write permission for the user. The file permissions should look like this. You may need to chmod the file accordingly :
-rw------- user user
This file (authorized_keys) can contain one public key per line. Anyone in possession of the corresponding private keys can login. The above tool just automates this process.
Warning : Your private key should always remain with you and you ONLY. If you lose this key, anyone in possession of it can access your servers.
Done? Great! - we can now test this out. Try to ssh into your VPS, if all went well you will be logged into your VPS and won't be asked for a password (if you selected not to give protect your key a passphrase). If it didn't go well troubleshoot and figure out what went wrong. Now let's turn off password access.
*Make sure that your ssh key login is working before you do this next step or you could lock yourself out of your machine.
Now head straight for the sshd config file, located at /etc/ssh/sshd_config Open it with your favourite text editor (I usually like nano or vim) as the super user. You'll find a line which says something similar. The '#' means it's commented out.
You need to un-comment it and change it as such
There are a bunch of settings in this config file that you can change to make your system more secure. I'll list a few key ones. These are not hard and fast rules, and there are many situations in which you may need Forwarding etc, so please look at your own requirements before implementing this. My suggestions would be:
I've pwned machines in the past (white-hat) with forwarding enabled, and that enabled me to use the machine as a proxy to route my traffic to internal hosts, or use the pwned machine as a relay for further attacks on the public internet.
After making the changes to this file, you can save it and restart your ssh server. If your server uses systemd the command for this is :
sudo systemctl restart ssh
Once you do this, passwords won't work anymore for logging in and all bruteforce attempts will be dropped pre-auth. Congratulations, you've saved yourself from a lot of potential threat.
Bots look for SSH on port 22. If it's not there, most of them just move on and don't start brute forcing. Using the same sshd_config file, you can change the listening port.
Warning : There is a possibility of locking yourself out of your system. If you understand the following completely, then you may safely proceed. If your system has a firewall in place (some of them do by default), then you will need to figure how to open whatever new port you choose to shift your ssh service to. If you don't do this, you could be locked out. Some cloud hosting providers keep your VPS on an internal IP address only, and they have NAT and port forwarding in place to allow access to services. If you change the ports that services listen on internally, you'll have to configure the port forwarding to redirect to your new port. You can check if this is the case by running 'ip a' and look at your ip address. If it doesn't match your public IP, then this is definitely the case.
After you change the listening port, you can restart your ssh server similarly and connect using the -p flag with the ssh command. Check 'man ssh' for more details.
Blocking attacks at the application layer can be a bit expensive in terms of processing power. Sometimes blocking malicious IP addresses at the IP layer from the kernel itself is a much more computationally efficient process. Fail2ban is a great tool that works as such. If a particular IP address fails to authenticate x number of times in y minutes, that IP address will be in a 'jail' for z minutes. A 'jail' is basically a set of firewall rules that drop packets from that particular host for the given period of time. Read up about the tool - it's great and it works with a whole lot of services.
Be sure to only install trusted software and tools on your VPS. If you're installing anything from outside of your native package manager and trusted repositories, do your due diligence. Verify checksums, shasums and signatures on all code that you are compiling. Make sure that your tools are not backdoored - only get software from trusted sources.
Never install pirated software or nulled software. I've seen many instances where people install nulled Wordpress plugins and get their servers P*wned. You pay for what you get - steal, and you will be stolen from. Unless you're good enough to read thousands of lines of code and spot a backdoor obfuscated in the code, don't try to install anything pirated. It's usually cheaper to just pay for the software, and enjoy the support of the development team.
Stay up to date
Use your package manager to keep your software up to date. Remove unwanted/obsolete software
Setup a firewall on your system and allow access to only ports that you need. UFW is easy to learn for beginners, and can be setup in minutes. If you're a power user, it maybe worth your while to invest time into studying IPTABLES.
Warning : Keep track of where your SSH server is listening - close this off and you're locked out :).
Build your tools
Alright - this one's more for the power users out there - it might not be relevant for a beginner level, but wherever you're at, give it a read through. If it doesn't make sense right now, put it at the back of your head and someday it'll come forward when you need it! While package managers really make life easy for us, convenience always comes at a price. Package managers will take care of all the dependencies and updating software is also a lot easier.
# apt-get install something
is a lot easier than
$ git clone something $ ./configure --[tons of configuration options] $ make [Debug the hell out of it and repeat] $ sudo make install
However building your own tools has a very distinct security advantage. Let us take for example, the web server nginx. If you install it with the package manager, chances are you will not be getting the latest stable version, which has a number of security and performance improvements. You could run the following experiment for yourself. Install nginx with your package manager and then run the following command
$ sudo nginx -V
You will see the details of the nginx build, including the modules that it was built with and all the 'configure' options. You'll find that there are plenty of modules that you will not ever use. For example, the pop3 module, imap module, scgi module may not always be necessary for your use depending on the application(s) that nginx is serving on your system. Manually building nginx has a very distinct advantage of giving you the latest and greatest version, and building it with only exactly what you need, giving you that lean, mean build that will serve you for years to come.
Just the basics
The above suggestions are just the basics - but they will give you a powerful start on securing your server. You will have taken strong steps in the right direction and made yourself a difficult target for automated bot attacks. Hardening a production server is an art in itself and is not for the faint of heart. However it is a necessity on the internet today. Feel free to drop your comments and let me know what you think. If you feel I've missed something important then please put it below.