All of our infrastructure is virtualized and hosted by a cloud vendor. We have machines to host our company tools as well as machines to host our own applications such as trackr. For trackr there are actually two environments, one to run the tests against and, of course, the production environment.
These days you can get a new virtual machine (VM) provisioned within a matter of minutes. Once a machine is up and running you can access it via the Internet and tailor it to your specific needs.
However, usually these machines come with a fresh installation of Ubuntu server (or another Linux, but that’s what we are using) with a default set of security measures. But since now everyone can potentially access your VM you might want to ensure that it is sufficiently secured.
So this is what this article is about. It will briefly show you how to configure Ubuntu to increase your security. Nevertheless, security is a process, not a product, as the saying goes so this is just an introduction to get you started.
For this article I’ve made some initial assumptions so you might not be able to apply everything one-to-one. First of all I assume that your virtual machine is running at least an Ubuntu Server 12.04 LTS. I also assume you are running Ubuntu or Mac OS on the client since both operating systems come with a set of handy tools we are going to use. Last but not least I will use the terms VM and server interchangeably. So let’s get started!
Once the machine is available you can usually connect to it via SSH using some predefined credentials. The problem is that for one you will most likely use port 22 to connect to the machine since it is the default. On the other hand, using password-based authentication is vulnerable to guessing attacks so you should avoid that as well by using a more secure approach as we will see in a bit.
Connect to the machine and first of all update the installed applications. As the heartbleed bug has taught us, there are even flaws to libraries that have been considered secure for years so staying up to date will make sure you are not vulnerable to attacks targeting a specific security flaw. You can update and upgrade the system just like so:
sudo apt-get update sudo apt-get upgrade
Adding a New User
The first thing we will do is to create a new user. This is important because many providers will send you credentials for the root user. Since Ubuntu has this user by default and attackers can easily try to guess the corresponding password using brute force measures it is a bad idea to go with it. You can create a new user and assign it to the admin group as follows.
sudo adduser batman sudo adduser batman sudo
After you’ve submitted the first command you have to type a password for the new user as well as some basic information such as the name. Once completed you can submit the second command which adds our user to the admin group so we can run scripts with root privileges.
Finally switch to the new user.
The next thing we want to change is the password-based authentication. A way more secure approach is to use public-key cryptography. You generate a pair of keys, a public one to be shared with the world and a private one that you should keep at a safe place where no one can access it.
I won’t delve into the details here as this is far beyond the scope of this article. However, the basic idea is as follows:
- you store your public key on the server.
- you store your private key on the client accessing the server - do not keep it anywhere else.
- when you try to connect, the server generates a random string and encrypts it using your public key which it is already aware of.
- your client decrypts the string using the private key and sends it back to the server.
- the server verified that the string has been decrypted correctly.
- a secure connection is established.
Since these keys usually consist of at least 1024 characters they are very unlikely to be guessed by brute force attacks. However, in case someone can get hold of your private key you are doomed so you should keep it safe.
Enough theory, let’s create the keys. In order to generate the key pair on the client from which you will access the server you can run the following command.
ssh-keygen -t rsa -C "batcave production server"
Again you’ve been prompted to enter some details, such as the file name.
In case this is your first key you can use the defaults. What you shouldn’t skip, however, is providing a passphrase.
In case someone gets hold of your private key then this will be an additional hurdle an attacker has to overcome.
If you accepted the default values then your keys will be stored in
Now that you have both keys you have to copy the public ones (
id_rsa.pub) to the server.
There are a handful options to achieve this, i.e. opening an SCP connection from a file manager,
but there is an even more convenient way using
The tool lets you copy a public key to a server which you still have password-based authentication enabled for.
ssh-copy-id -i /home/bruce/.ssh/id_rsa email@example.com
As you can see you can specify an identify file (
-i) which is handy in case there are more keys available.
You also have to provide the credentials and the server to connect to, so the tool knows where to actually store the key.
Let’s see whether this already worked by opening an SSH connection from the client.
If all went well you should no longer be required to submit a password.
On the virtual machine you can now verify that the public key has successfully been stored.
By default it is added to
You can add more keys to the file if you want to, i.e. one for each client you use to connect to the server.
By now we have a dedicated user and enabled public key authentication. But users can still login with a password and even worse, SSH also allows root logins by default, so let’s change that.
/etc/ssh/sshd_config you can see the configuration for the SSH service.
As we want to change some things you should open it with an editor of your choice now and change the following settings.
Port 945 PermitRootLogin no PasswordAuthentication no
So what have we done here? The config pretty much speaks for itself so you can see that we no longer allow users to login as root.
We eventually also disabled the password-based authentication which is fine since we already stored our public key on the server.
Finally we changed the port from
This will not secure your service by default, rather it will only slow down potential attackers.
So you might want to install additional tools to monitor your server for unauthorized access.
Save the file and restart the SSH service with
sudo service ssh restart
We will configure the firewall in the next step which will block all traffic except that on port
In case you didn’t reconnect before now is the time to do it.
Make sure to also specify the correct port since SSH assumes port
22 in case no other information are given.
ssh firstname.lastname@example.org -p 945
Update: there is an awesome article accessible here about how to ease the use off SSH. Highly recommended.
Activating the Firewall
Now that SSH is optimized, the last step is to configure our firewall.
iptables to manage incoming and outgoing traffic.
Since it might overwhelm new users a little, there is an easy interface that we will use called uncomplicated firewall.
You can install it via
sudo apt-get install ufw
I assume that there are currently no other services running that would require an open port (such as a web server) so we will configure the firewall to deny all traffic by default but allow access to port
945 to use the SSH service.
This can be achieved using the following commands
sudo ufw default deny sudo ufw allow 945/tcp sudo ufw enable
ufw will warn you that enabling the firewall may disrupt existing connections, but since we took care of this already you shouldn’t get disconnected. Now you can review the settings with
sudo ufw status verbose
This should yield something similar to this:
To Action From -- ------ ---- 945/tcp ALLOW IN Anywhere 945/tcp ALLOW IN Anywhere (v6)
Changing firewall rules always bears the risk of locking yourself out of your machine so you should be cautious whenever you make any changes. When you bricked a newly setup machine then this might not be an issue as you can destroy and recreate it easily without losing any data. However, if you are late to the game and only add security to a production system you can use a fix which I’ve learned of recently from The Official Ubuntu Server Book, using a cron job to occasionally disable your firewall:
*/15 * * * * root /usr/sbin/ufw disable
It goes without saying that this tears down your entire firewall and leaves you vulnerable to the outside if you forget about disabling the job once you’re done. Thus I wouldn’t recommend it.
Congratulations - you just increased your level of security making it harder for potential attackers to get hold of your precious machines. However, this article merely scratched on the surface of how you can secure your machines. Everything described here will only give you some additional time (at best) but not protect you from getting hacked. Increasing your system’s security is pretty much worthless unless you constantly monitor it for intrusions and suspicious activities. A good guide to get you started I’ve found particularly helpful can be found here.
How do you secure your machines? Did we miss something? Do you want to share your experiences? Give us a shout!