Any discussion about securing a server these days is incomplete without mentioning firewalls and their importance. Firewalls are central to your ability to protect your server from attacks from the network, and give you great control over who can and cannot connect to the services running on your server. In this article we will cover what firewalls do, why they are important even if your server is not exposed to the internet, and how to set up and manage a very capable linux firewall.
Firewalls control the network traffic connecting to, and leaving from, your server, based on its IP address and/or port number. You can control to quite a granular degree, who can connect to the services running on your server.
When you connect to your home server you do so using its IP address or hostname if you have name resolution set up. For the various services running, you will also be using a port number. Often this doesn’t need to be given with the IP address, the web browser, file browser or other application you are using knows the default port number for that service. There are 65,535 possible ports available on your server, and they are like the various channels on a TV, all coming into your home on the same connection. What a firewall does, is only allow connections to the ports you have specifically permitted, and block any attempts to connect to any other ports
Firewalls can also go into greater detail, and specify that only certain IP addresses can connect to certain ports/services, but we are not going to cover that level of detail here, as it is probably less likely to be needed on a home network.
Your most fundamental firewall is the router supplied by your ISP. Unless it has been configured otherwise, this is blocking all attempts coming from the external internet to connect to machines (servers or personal computers) inside your home network. This does not mean you can be complacent about running a firewall on a server which is inside your network though. If a laptop or phone which is infected with malware is brought into your home, and connects to your wifi, it is now on your network and behind the router firewall. If malware (or a hacker) is able to scan your server and find vulnerabilities in software or the operating system, they can launch exploits which will bind to an unused port and give them a persistent connection into the server. Strong firewall rules can help you mitigate this risk by shutting down any unused ports and provide another layer of defence.
With all this being said, you might be surprised to hear that the Ubuntu server comes with its firewall disabled! It is up to us to configure and enable it. The most popular linux firewall is called IP tables, but it can be a bit complex to manage by itself and its commands are a little heavy to master. We are going to use the popular and much easier to use front end called UFW, or Uncomplicated Firewall. This is still configured from the command line, and it makes for a much more user-friendly way to configure the firewall on your home network.
Configuring Uncomplicated Firewall
While IP tables is already part of your server the first thing we need to do is install UFW
sudo apt-get install ufw
This will install, but not turn on the firewall yet. UFW has default rules to deny all incoming traffic, and allow all outgoing traffic. This means that if you are configuring it remotely over the network, via SSH, and turned it on right away, you would lock yourself out of your own server! Thus your first step is to allow incoming SSH connections. If you are connected directly to your server though, that is using a mouse, keyboard and monitor, you are not using a network connection, and so you would not be locked out. SSH is very useful for connecting remotely and securely, so you can pack the server away somewhere and connect to it over the network/wifi.
sudo ufw allow 22/tcp comment ‘SSH’
With this set, you can now enable the firewall
sudo ufw enable
You can check the status of the firewall rules by running one of three commands:
sudo ufw status sudo ufw status numbered sudo ufw status verbose
The first command shows the basic status of the rules, i.e. ALLOW connections coming in on port 22 (SSH) from Anywhere, that is from any IP address. Adding the ‘numbered’ argument shows the number of each rule, allowing you to sort them as needed. The ‘verbose’ argument lists additional information such as the level of logging and the default policies.
When we added the rule allowing SSH traffic (port 22), UFW created two rules, one for IPv4 and one for IPv6 traffic. It is not likely that you are running IPv6 on your home network so let’s disable it, if only to keep your firewall rule listing tidy. Navigate to /etc/default, and make a copy of the UFW config file
cd /etc/default sudo cp ufw ufw.BACKUP
Then use the nano text editor to edit the ufw config file
sudo nano ufw
Change the entry for IPV6 from ‘IPV6=yes’ to ‘IPV6=no’, press Ctrl + O to save and then Ctrl + X to exit. Finally disable and reenable the firewall to make the changes
sudo ufw disable sudo ufw enable
Run a ufw status command again to verify that the IPv6 rules are no longer showing.
As you install various applications on your home server, such as Samba for file sharing, a web server, a torrent server, media server, etc., pay attention to the ports needed to access the service. Port numbers are quoted after the IP address, separated by a semi-colon, i.e. 192.168.1.100:22 for the SSH port (absolutely necessary for connecting to your server remotely!). When you have a firewall running, if you don’t allow access to that port number, you will not be able to connect to it across the network.
For a web server, to allow web connections to it, you would run:
sudo ufw allow 80
Note, this will allow permit both TCP and UDP traffic on port 80. As HTTP only uses TCP, we will specify this. It is good practice for your firewall rules to be very specific as to what traffic it is allowing in:
sudo ufw allow 80/tcp comment “HTTP web traffic”
UFW also allows you to use the service names, and it will automatically apply the correct port and protocol. It does this by reading the /etc/services file, which lists services and their respective ports. To allow web connections, for example, you can allow ‘http’, and UFW will see that this translates to 80/TCP:
sudo ufw allow http comment “HTTP web traffic”
To use the rules above as examples, if you want to delete a rule from your ruleset, run:
sudo ufw delete allow 80 sudo ufw delete allow 80/tcp sudo ufw delete allow http
As ‘allow 80’ was the rule you added to your firewall, then this is the specific rule you tell UFW you want to delete. There is another way also.
If you use the ‘status numbered’ command, UFW will show a number beside each rule. To delete rule number 2 then, you would enter:
sudo ufw delete 2
Once you have a few rules in your firewall ruleset, you will notice that the ufw status doesn’t display them in numerical order but rather in the order you added them. This is an important concept to understand, and is key to how firewalls work.
Imagine you wanted to block all SSH connections (port 22/tcp) to your server, except SSH connections from one machine, whose IP address is 192.168.1.3. Your UFW firewall has the two rules below in it. What do you think will happen?
 Deny 22/tcp  Allow 22/tcp from 192.168.1.3
The order of firewall rules is vitally important, and the first match wins. In this case, the first match says that all SSH traffic is denied, so even if you are connecting from 192.168.1.3, your connection would be denied. When adding rules, you must add the more specific rules first, and the more general rules afterwards. Luckily there is a way to do this.
Running a numbered status command shows you the number/position for each rule in the ruleset. In the case below, you would delete the existing ‘allow 22/tcp’ rule, and then run the command below to re-enter it in position 1, that is ahead of the Deny rule:
sudo ufw insert 1 allow from 192.168.1.3 to any port 22
Check for Listening Ports
While working with firewalls, it is interesting and useful to know what services on your server are actually listening for incoming connections. Maybe you’re interested in what network services you are running, or you want to know what ports need to be opened on the firewall. Luckily you can do this using the netstat command.
Netstat is an age-old command for showing many network related statistics and details. It can show you a great deal of information on your network connections, but I would argue that details on connections being created, waiting, closing or closed are of limited use to us. Mainly you will be interested to know what ports are actively listening for connections or what connections are already established.
There are a variety of options to be used to get different results with netstat, and I would recommend you try various combinations of them all to see which gives you the best result for your needs.
|-a||show all connections. Can result in a lot of data|
|-4||show IPv4 connections only|
|-6||show IPv6 connections only|
|-t||show TCP connections only|
|-u||show UDP connections only|
|-l||show LISTENING connections|
|-n||do not try to look up hostnames for IP addresses. This can sometimes slow down results, though it can sometimes also make for a cleaner result|
|-p||show the program making/listening for the connection|
To show all programs listening for IPv4 TCP connections, use:
sudo netstat -4tlnp
The results screen shows you the Protocol (TCP/UDP), stats on bytes Received and bytes Sent, the Local server IP address and port number, the Foreign Address, i.e. the IP address of the computer connected to your server, the State and the Program name behind the port. For Listening connections, which are not active, there will be no Foreign Address. To show the current, established, connections to your server, run:
sudo netstat –ap | grep ESTABLISHED
Here you can see the same protocol, bytes received/sent and local IP address data. Now though you also see the IP address of the computer/laptop/phone/network device which is connected to your server, and what its connection is for. If you used the -n flag also, you will see the hostname or DNS name of the foreign device, which may be helpful in identifying just what it is.