Securing a new Ubuntu install
Some first steps to take to secure your new Ubuntu VM
First steps
So you've provisioned a shiny new Ubuntu OS on Digital Ocean or Linode, and the first thing you will want to do is lock it down. It's scary how quickly automated bots will find the newly provisioned server, start scanning for open ports and attempting to log in so they can turn your shiny server into a spewer of Viagra emails and promises of millions of dollars if you'll just hand over your name, date of birth and passport number.
Once the machine has booted up, you need to ssh
to the server using it's IP address.
$ ssh root@SERVER_IP_ADDRESS
Once logged in the first thing to do is get any and all updates for the OS. So at the prompt run:
$ apt-get update
Followed by:
$ apt-get upgrade
Once all the updates have installed it may ask you to reboot.
A wild User has appeared
Now you want to create a new user account for all your normal use of the server. It's never good practise to be logged in as root
on your system. Given the supreme power that root
wields on a Linux server, it's far too easy to cause irreperable harm without meaning to.
In these examples we'll use the example username bob
(as it's small and easy to remember).
So at the terminal enter:
$ adduser bob
The system will ask you a few questions, one of which being what password you want. Make sure you enter a strong one.
The rest of the questions you will mostly leave blank if you are anything like me.
Escalating privileges
So this new user account just has standard user priviledges which won't be enough for those odd occasions when we do actually need to perform adminstration functions on the server.
To do this we will make use of the sudo
command. "Sudo" gets put in front of any command that you wish to run with root priviledges. But to make use of this command we first need to add the user to the sudo
group.
So still logged in as root
, enter the following:
$ gpasswd -a bob sudo
Before performing the next step you may want to log out of root
, log in with your normal account and ensure that the sudo
command works as expected.
Disable root SSH login
So now you have your normal user account with sudo
priviledges, you want to disable remote root access to the server. Root
is one of the first user names the bots will attempt to access when scanning your server. Disallowing anyone to log in as root remotely removes that risk entirely, as now the attacker needs to know your personal username (you didn't use something simple like admin
did you?) as well as your very strong password.
So enter the following:
$ sudo vim /etc/ssh/sshd_config
Then search the file for the section which says PermitRootLogin
and set it to no
.
PermitRootLogin no
Save the file and exit vim. However, before restarting the ssh
service make double (or triple) sure that your normal account has sudo
priviledges otherwise you will have just locked yourself out of being able to admin your own server!
Once you are sure your account has the correct access, enter the following:
$ sudo service ssh restart
Public Key Authentication
The next step is to setup Public Key Authentication so you don't need to type in that pesky password every time you access the server.
If you don't already have an ssh
key setup, then creating one is simple. At the console of your local machine, enter the following:
$ ssh-keygen -t rsa -C "[email protected]"
# Creates a new ssh key, using the provided email as a label
# Generating public/private rsa key pair.
# Enter file in which to save the key (/Users/you/.ssh/id_rsa): [Press enter]
This generates a private key, id_rsa
, and a public key, id_rsa.pub
, in the .ssh
directory of the localuser's home directory. The private key is exactly that, private; do not share it with anyone.
Then from the home directory on your local machine enter the following:
$ cat ~/.ssh/id_rsa.pub
This will print your newly generated public key to your console which you can then copy to your new server.
So ssh
back into your server using your normal user account, and make sure you are in your user's home directory. Which in this this example looks like:
$ pwd
/home/bob
Now create a new folder called .ssh
. We also need to restrict the permissions so that if we have any other users on this system they can't access our ssh information.
$ mkdir .ssh
$ chmod 700 .ssh
Now create a file in the .ssh
directory called authorized_keys
.
$ vim .ssh/authorized_keys
Paste your public key into the file, save it and exit. Then restrict access to it.
$ chmod 600 .ssh/authorized_keys
You should now be able to log out, and then log back in using your private key as authentication.
Firewall
Next up is to setup a basic firewall. A firewall basically denies incoming traffic to every port on your server. Ubuntu has a simple one called ufw
already installed. All we need to do to make use of it is tell it which ports we actually want to open to accept traffic, and then turn it on.
As we ssh
into this remote server, that's the first port we need to open, otherwise we will manage to lock ourselves out of our own server again.
$ sudo ufw allow ssh
This is the bare minimum you need to setup, but if you plan on using your server for additional services (such as a webserver) you will need to open each port required. Http(s) for example requires the following:
$ sudo ufw allow 80/tcp
$ sudo ufw allow 443/tcp
And email would also require:
$ sudo ufw allow 25/tcp
Once you think you have finished adding enough services you can see the rules with the following:
$ sudo ufw show added
And if you're happy with everything, lets turn it on!
$ sudo ufw enable
You will be asked to confirm that you want to turn the firewall on - you did add the ssh
rule right? - and once accepted the firewall will apply all your rules to all incoming traffic.
NTP
Installing NTP will allow your computer to stay in sync with other servers. On Ubuntu all that is required to setup time synchronisation is type in the following:
$ sudo apt-get update
$ sudo apt-get install ntp
Read only shared memory
A common exploit vector is going through shared memory (which can let you change the UID of running programs and other malicious actions). It can also be used as a place to drop files once an initial break-in has been made.
So the first thing we will do is secure the shared memory. Enter the following into the command prompt:
$ sudo vim /etc/fstab
Then add the following line at the bottom of the file:
tmpfs /dev/shm tmpfs defaults,ro 0 0
Exit and save the file, then reboot the system.
Fail2ban
Lots of servers get a steady stream of attacks on ssh
. To make it harder for any would-be attacker we can use Fail2ban which makes use of iptables to block an attacker for a defined period of time.
$ sudo apt-get update
$ sudo apt-get install fail2ban
The fail2ban service keeps its configuration files in the /etc/fail2ban
directory. The default configuration file is called jail.conf
. Since this file can end up getting modified by package upgrades, we shouldn't edit this file in-place, but rather copy it so that we can make our changes in relative safety.
In order for fail2ban to find the configuration file we need to copy the default file to jail.local
.
$ sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Once the file is copied, we can open it for editing to see how everything works.
$ sudo vim /etc/fail2ban/jail.local
The first section in the file is labelled [DEFAULT]
and the settings listed in there are applied to all following services.
The first thing to change is the length of time that a ban is instituted for.
bantime = 1800
We also need to configure the email address to which all alert information will be sent to.
destemail = [email protected]
You can also set the sendername
to something else if you'd like. It's useful to have a value that can be easily filtered using your mail service though, else your inbox may get flooded with alerts if there are a lot of break in attempts from various places (and there will be).
Further down the file you will see a setting called action
.
action = %(action_)s
You will want to change the line to look like the following:
action = %(action_mwl)s
This will enable the email of all reports and will also include the log files for easier debugging in the event that something does happen.
The last section of the file lists all the different services that fail2ban can be configured for. We want to ensure that fail2ban is setup for ssh
- and if for example you are running a blog or website on nginx
then you will also want to enable it for http authorisation attempts.
Simply locate both the [ssh]
and [nginx-http-auth]
sections and set enabled
to true in both.
enabled = true
Once you're happy with your settings save and exit the file, then restart the fail2ban service.
$ sudo service fail2ban restart
It won't be long until you start receiving emails informing you of all the IP addresses that have been blocked.
Restrict access to "su"
We only want to allow admin users to use the su
command. This helps prevent privilege escalation attacks. Ubuntu may already have an admin group but if not, run the following:
$ sudo groupadd admin
Then add yourself to the group
$ sudo usermod -a -G admin bob
Now restrict access to /bin/su to admin group members
$ sudo dpkg-statoverride --update --add root admin 4750 /bin/su
You can then check these permission with the following:
$ ls -lh /bin/su
And you should see the following:
-rwsr-x--- 1 root admin 31k 2011-11-24 14:16 /bin/su
Sysctl Hardening
Now to harden the IP stack.
$ sudo vi /etc/sysctl.conf
Now locate the line:
net.ipv4.conf.all.accept_source_route=0
You should just have to uncomment it. Then below it add the following line:
net.ipv4.conf.default.accept_source_route=0
You could use the sysctl command to do these instead but this way they will persist beyond a reboot.
Check for rootkit presence
Chkrootkit
scans the system for evidence that a rootkit has been installed. This is a confidence test to be used to check whether your system has been compromised. It’s worth running periodically.
To install:
$ sudo apt-get install -y chkrootkit
Then to run it:
$ sudo chkrootkit
At the time of writing there seems to be bug with chkrootkit
that lists /sbin/init
as containing a Suckit rootkit infection. This is a false positive.
Detect attempted intrusions
Psad
is a collection of lightweight daemons that log attempted intrusions, in particular monitoring iptables.
$ sudo apt-get install -y psad
The daemons will run automatically once installation is complete. To check the current status:
$ sudo psad -S
You can modify the psad settings to e-mail the admin on the event of an intrusion detection.
Watch those logs
The most detailed and informative logs in the world are about as much use as a chocolate teapot if no one looks at them. Logwatch winnows the deluge down to a succinct report which hopefully you will look at.
$ sudo apt-get install -y logwatch
Then to produce the report:
$ sudo logwatch | less
Ongoing maintenance
Now that the server is more secure, once a week perform on-going maintenance like ensuring your software is up to date:
$ sudo apt-get update
$ sudo apt-get upgrade
And done
That's it. Your server should now be a lot more secure than it was before. However bear in mind, no matter how secure a system, a determined and skilled attacker will always find a way in; but at least now the job is a lot harder and this should protect you from the majority of bots out there.
Enjoy your new server!