Secure your server with UFW

Server security is an important part of every website, especially when you are storing sensitive customer information. I recently started investigating ways of hardening our hosting environment and enabling the firewall was the first logical step.

In general, my hosting environments run on Ubuntu. By default there are a couple of options available right out of the box. Ubuntu ships with iptables and ufw. My choice was to go with UFW for it's simplicity and quick learning curve.

What is it?

UFW, or Uncomplicated Firewall is the default firewall configuration tool for Ubuntu. It was created to simplify the configuration of iptables and provides a user friendly way to create an IPv4 or IPv6 host-based firewall. By default it's disabled.

Getting Started

Even though UFW normally ships with Ubuntu, let's make sure it's installed. To do this, lets run:

which ufw  

You should see something like:

/usr/sbin/ufw

If you don't get any output, that means we need to install it. You can easily do this with apt-get or aptitude by running:

sudo apt-get install ufw  

or

sudo aptitude install ufw  

Defaults

Before we turn UFW on, we should add a couple of rules to help protect our server. Let's start with a couple of defaults to get us going and then add some more specific rules based on how we will be using our server. UFW's defaults are to deny all incoming requests and allow all outgoing. This means anyone trying to connect to the server will not be allowed, but the internal applications can still reach out. Let's make sure these rules are active by running the following:

sudo ufw default deny incoming  
sudo ufw default allow outgoing  

Note: for a little added security, you could also deny all outgoing connections and only open up the ports you know you'll need for your application.

Allowing what we need

There are a couple of different ways to allow connections to our server. UFW provides a simple and complex way of setting up rules. If you would like to enable a specific service you could just run:

sudo ufw allow ssh  

This is essentially just shorthand for:

sudo ufw allow 22/tcp  

As you can see, this would open up port 22 on the TCP protocol. If your SSH server is running on a different port, we could instead enable connections to that with:

sudo ufw allow <port number>/tcp  

You could also enable an entire port range, like 2345 through 3456 by issuing the following command:

sudo ufw allow 2345:3456/tcp  

or on a different protocol, like UDP:

sudo ufw allow 2345:3456/udp  

IP Specific Rules

To enhance our security rules further, it's a good idea to only allow certain services access based on their IP address. Specifically, I like to only allow SSH connections from the places I work, like my home or office. To add a rule with an IP address, use this command:

sudo ufw allow from 12.34.56.78  

This would allow IP address 12.34.56.78 to connect to any port on our server. Let's tighten that up by telling UFW which port and protocol we want to allow access:

sudo ufw allow from 12.34.56.78 to any port 22 proto tcp  

Now IP address 12.34.56.78 would be allowed to connect to port 22 specifically.

Denying Access

Up until now, we have been only adding rules to allow access to our server. But it is simple enough to deny access as well. All we have to do is swap in deny in place of allow. Say you wanted to ban a specific IP address after having been attacked. You could add a rule to ban that IP on all ports with:

sudo ufw deny from 98.76.54.32  

If you wanted to ban that IP on a specific port:

sudo ufw deny from 98.76.54.32 to any port 80  

Deleting Rules

Oops, you made a mistake about that IP address and no longer want to ban them. We can remove the rule by simply adding delete to the front of it:

sudo ufw delete deny from 98.76.54.32 to any port 80  

When your rules start to get long and complex though, it might be easier to remove them based on a specific id. Two steps are involved to remove rules in this way. First we have to get a list of our current rules (with numbers) using the following command:

sudo ufw status numbered  

Note: for this to work, you have to have UFW already enabled (continue reading to find out how to enable it). If it isn't, you will just be presented with the prompt again.

This will give us output similar to the following:

Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22/tcp                     ALLOW IN    Anywhere
[ 2] 2345:3456/tcp              ALLOW IN    Anywhere
[ 3] 2345:3456/udp              ALLOW IN    Anywhere
[ 4] Anywhere                   ALLOW IN    12.34.56.78
[ 5] 22/tcp                     ALLOW IN    12.34.56.78
[ 6] Anywhere                   DENY IN     98.76.54.32
[ 7] 80                         DENY IN     98.76.54.32
[ 8] 22/tcp (v6)                ALLOW IN    Anywhere (v6)
[ 9] 2345:3456/tcp (v6)         ALLOW IN    Anywhere (v6)
[10] 2345:3456/udp (v6)         ALLOW IN    Anywhere (v6)

Now, to delete one of the above rules, just type in:

sudo ufw delete <number>  

Let's start it up

Remember, by default UFW is disabled, so after we have all our rules setup, it's time to turn it on. Be careful though, if you have closed up connections to everything and haven't added a rule to allow access to port 22 (which you are most likely connected to the server on via SSH) you could get disconnected (although in my experience, the server won't actually close your connection, it will just refuse it the next time you try to connect). With that in mind, let's start it up!

sudo ufw enable  

If all went well, you should see nothing but the prompt again. Now that we are up and running, you can check the current status with:

sudo ufw status  

or, if you'd like more details:

sudo ufw status verbose  

In the off chance you want to turn the firewall off, you could issue the following:

sudo ufw disable  

Feel like you might have messed something up? You can always roll back to the defaults with:

sudo ufw reset  

Conclusion

You should now have a better understanding of how to setup a firewall quickly and easily using UFW, making your server much more secure than before. I'm only just getting started learning about server security myself, but so far I've found the following setup to be a good basic starting point if you're just setting up a simple website:

To                         Action      From  
--                         ------      ----
80/tcp                     ALLOW IN    Anywhere  
443/tcp                    ALLOW IN    Anywhere  
22/tcp                     ALLOW IN    YOUR_IP_ADDRESS  
80/tcp (v6)                ALLOW IN    Anywhere (v6)  
443/tcp (v6)               ALLOW IN    Anywhere (v6)  

If you'd like to take your SSH access security a step further, checkout my blog post about knockd called Enhanced Security with Knock.