Setting Up a UFW Firewall in Linux

Content:

Firewalls are an important part of internet security. They’re a vital tool when running an internet facing server. They monitor traffic to and from a server, and either allow or deny traffic based on a set of rules.

Servers need to allow some access to them, for accessing the content they provide, but can become targets for hackers if they are not secured correctly.

In this guide, we’ll take a look at setting up a firewall, using Raspberry Pi OS. This will also work on other Linux distributions – just replace the commands with the equivalent for your distribution.

Installing UFW

The software we’ll be using is called UFW, or Uncomplicated Firewall. Some linux distributions come with UFW installed as default.

To try installing UFW, run the command for your specific Linux OS.

apt install ufw

If the software isn’t installed, allow it to install before continuing.

Enabling UFW

With UFW installed, we now need to enable it, by running the following:

systemctl enable ufw
systemctl start ufw

This will both enable the UFW service (causing it to automatically start on system boot), and start it now. Not that at this point, UFW will be blocking all traffic. Bare this in mind before starting the service on a critical system.

We can check that it is running using:

systemctl status ufw

The output should show that ufw is running.

● ufw.service - Uncomplicated firewall
     Loaded: loaded (/lib/systemd/system/ufw.service; enabled; vendor preset: enabled)
     Active: active (exited) since Mon 2022-01-31 14:58:47 GMT; 3 months 0 days ago
       Docs: man:ufw(8)
    Process: 148 ExecStart=/lib/ufw/ufw-init start quiet (code=exited, status=0/SUCCESS)
   Main PID: 146 (code=exited, status=0/SUCCESS)
        CPU: 361ms

Jan 31 14:58:47 server-dev systemd[1]: Finished Uncomplicated firewall.
Warning: journal has been rotated since unit was started, output may be incomplete.

Adding Rules to UFW

Currently, our firewall is runnking, and will be blocking all traffic trying to reach our system.

We can see the current list of UFW rules by running

ufw status

This will return both the current firewall status, and the list of rules that it is applying.

~ $ ufw status
Status: active

To                  Action      From
--                  ------      ----
22/tcp              ALLOW IN    192.168.0.0/24
137,138/udp         ALLOW IN    192.168.0.0/24
139,445/tcp         ALLOW IN    192.168.0.0/24
80/tcp              ALLOW IN    Anywhere
443                 ALLOW IN    Anywhere
9090/tcp            ALLOW IN    192.168.0.0/24
Postfix             ALLOW IN    Anywhere

We can run this command at any point after adding or removing rules, to check the rule has been added as expected.

Allowing Connections On A Specific Port

We can enable connections to a specific port using the command below.

ufw allow {port}

Simply replace {port} with the number of the port you wish to open. For example

ufw allow 22

will allow connections to be made over port 22, which is used for SSH.

You can limit this further by specifying extra parameters, such as the connection protocol allowed and the IP(s) allowed to use the port.

ufw allow proto tcp from 192.168.0.0/24 to any port 3306

This command is a little more complex.

The proto command specifies whether to allow tcp or udp connections through the port. When using this parameter, we must add both from and to clauses.

To allow all connections, specify any as the from parameter. You can allow only a single IP address, or an entire subnet, as in the example above. This command allows parameters from any address in the 192.168.*.* subnet, which means any local machine can connect.

With this more complex command, the word port must precede the port number.

In full, this command allows any device in the 192.168.0.0/24 subnet to connect to this machine through tcp on port 3306.

Allowing Connections on a Specific Interface

As well as targeting ports, you can also target entire network interfaces. If your machine has multiple ethernet ports, you might want to allow specific traffic through each network interface.

ufw allow in on eth0 from any to any port 25

This command allows access in through port 25 to any client, provided the connection uses the eth0 network interface.

Allowing Application Specific Connections

To make management simpler, UFW includes a list of predefined rules for specific applications.

We can see the list of applications using

ufw app list

The resulting list will have entries similar to the below.

AIM
Bonjour
CIFS
DNS
Deluge
...

I won’t include the full output, due to the length.

You can replace the proto and port sections of the previously mentioned commands to make use of the application profile.

ufw allow "SSH"
ufw allow proto tcp from any to any port 22

These two commands do the same job.

Denying Specific Connections

The sections above have all focused on accepting specific connections. Generally speaking, this will make up the bulk of your rules, as connections will be denied by default without a corresponding ALLOW IN rule.

You might, however, wish to block certain traffic over a port. For example, if you are running a website which will use ports 80 (HTTP) and 443 (HTTPS) by default, you will need to open these ports to everyone to allow general internet users to access your site.

If you notice certain IP addresses attempting to find exploits on your server (an expected situation with anything internet facing), you might decide to block that specific IP address from accessing your server.

ufw deny

This can be used with the same parameters as outlined above – just replace allow with deny.

It’s important to note that UFW reads rules in the order they are entered, so the deny rule would have to be listed above any less restrictive allow rules.

Deleting Existing Rules

The easiest way of deleting a rule is to find find the rule number.

ufw status numbered

You will get an output similar to our earlier result, but this time, with numbers on the left-hand side.

~ $ ufw status numbered
Status: active

     To                  Action      From
     --                  ------      ----
[ 1] 22/tcp              ALLOW IN    192.168.0.0/24
[ 2] 137,138/udp         ALLOW IN    192.168.0.0/24
[ 3] 139,445/tcp         ALLOW IN    192.168.0.0/24
[ 4] 80/tcp              ALLOW IN    Anywhere
[ 5] 443                 ALLOW IN    Anywhere
[ 6] 9090/tcp            ALLOW IN    192.168.0.0/24
[ 7] Postfix             ALLOW IN    Anywhere
[ 8] 3306/tcp            ALLOW IN    127.0.0.0/24

To delete entry number 8, run

ufw delete 8

When prompted, enter ‘y’ to confirm.

~ $ ufw delete 8
Deleting:
 allow from 127.0.0.0/24 to any port 3306 proto tcp
Proceed with operation (y|n)? y
Rule deleted

Checking Blocked Requests

If you’re finding that valid requests are not getting through to your system, or you just want to check what your firewall has been up to, you can check entries in the system journal.

journalctl | grep "UFW"

An entry similar to the below means a connection has been blocked.

[UFW BLOCK] IN=eth0 OUT= MAC=aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77 SRC=198.91.80.251 DST=192.168.0.1 LEN=60 TOS=0x00 PREC=0x00 TTL=48 ID=63664 DF PROTO=TCP SPT=51728 DPT=25 WINDOW=29200 RES=0x00 SYN URGP=0

There’s a lot of information here, so let’s break it down:

  • IN=eth0 – The network interface the request is using, in this case, ethernet 0.
  • OUT= – The network interface of the outbound request. In this case, this is not an outbound request, so it is empty.
  • MAC=aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77 – The MAC address of the network interface.
  • SRC=198.91.80.251 – The IP address of the request source.
  • DST=192.168.0.1 – The IP address of the request destination.
  • PROTO=TCP – The protocol the connection is using.
  • DPT=25 – The port the connection is using.

The other parameters are not important.

In this case, 198.91.80.251 is attempting to access port 25 on the server, using TCP.

This log can be very useful for diagnosing connection issues through your firewall, and it logs both inbound and outbound requests that are blocked.

If I was expecting a connection over port 25, I would have to add a rule to allow connections over this port. If I wanted to, I could limit the connection to only TCP, or even the specific IP address of this request, and it would still get through the firewall.

Conclusion

This is by no means a definitive guide covering UFW commands, but should provide enough information to add even the most complex of rules.

UFW is an incredibly powerful tool, and when it is configured appropriately, forms a key part of server security.