ufw Firewall Interface

ufw is a firewall program built by Canonical Ltd. to simplify iptables implementation and hosting its own firewall services. It is backward compatible with iptables rules.

Setup

To setup ufw, simply install it from your distribution repository. Example, for Debian:

$ sudo apt install ufw -y

Set Default Rules

Before starting to set any rules, you should always set the default defense parameters. They are:

$ sudo ufw default deny incoming
$ sudo ufw default allow outgoing
$ sudo ufw default deny forward

If you're hosting NAT private network for your VMs, you might want to allow forward. Otherwise, your VMs cannot get any network connections at all:

$ sudo ufw default allow forward

Start/Stop Firewall

To start/stop ufw firewall, just use the enable/disable command.

START

To start running firewall:

$ sudo ufw enable
Firewall is active and enabled on system startup
$


STOP

To stop running firewall:

$ sudo ufw disable
Firewall stopped and disabled on system startup
$

Adding Firewall Rules

ufw allows various way of adding firewall rules into your system. We will look into each of them individually from the very basic to . You add by using your action (allow/deny) then the rule statement. Example, if I want to allow a connection, the command would be:

$ sudo ufw allow <RULE STATEMENT>

if I want to deny a connection:

$ sudo ufw deny <RULE STATEMENT>

If any connection does not comply to any rules, it will follow the default rules set above.

For the following cases, we will be using allow to simplify our explanation. Of course, you can use deny anytime if you want and when it makes sense.


Anywhere (Public and Private) to Port

Let's say if we change our mind and now we want to expose a port to the world, the command is:

$ sudo ufw allow <PORT>

Example, say we want to expose our SSH port 22 to the world, it is:

$ sudo ufw allow 22

if you check the rule, you should get something like:

$ sudo ufw status
Status: active
To                    Action     FROM
--                    ------     ----
...                   ...        ...
22                    ALLOW      Anywhere
22 (v6)               ALLOW      Anywhere (v6)



Specific IP to Port

Let's start with the basic: FROM <SOURCE> TO <PORT>. The command is:

$ sudo ufw allow from <SOURCE_IP> to any port <PORT NUMBER>

Example, say we want to allow 192.155.13.121 to access port 22, it is:

$ sudo ufw allow from 192.155.13.121 to any port 22

If you check the rule, you should get something like:

$ sudo ufw status
Status: active
To                    Action     FROM
--                    ------     ----
...                   ...        ...
22                    ALLOW      192.155.13.121



List of Specific IPs to Port

Let's say if we change our mind (again) and now we want to allow a range of IPs, we can use the IP and Subnet Masking as a replacement of source IP. Example, for a full range of IPs from 192.168.122.1 to 192.168.122.255, you use 192.168.122.0/24 as SOURCE_IP.

Hence, using the previous section example, the command should be:

$ sudo ufw allow from 192.155.13.1/24 to any port 22

NOTE:

  1. The ending is called sub-mask, where it simply means:
    • /32 - 255.255.255.255
    • /24 - 255.255.255.0
    • /16 - 255.255.0.0
    • /8 - 255.0.0.0
  2. If you want specific lists and are not in a a range as shown above, the best way to do is to script the list in a BASH script and perform individual addition over a loop.


Specific Network Interface to Port

Let's say we change our mind (again and again) and now we want to only allow a specific network interface (e.g. eth0) to connect a specific port, you use a different command that has "in on <interface>" keywords:

$ sudo ufw allow in on <INTERFACE> to any port <PORT>

Example, say our network interface is eth0 to port 22, we get:

$ sudo ufw allow in on eth0 to any port 22



Specific IP to List of Ports

Let's say we change our mind (seriously, again?!) and now we want to a list of ports in range, we use BEGIN:END/protocol format as the PORT value. Here is the command format:

$ sudo ufw allow from <IP> to BEGIN:END/protocol

Based on the example above, say from 192.155.13.121 to access port 1000 to 2000 using TCP protocol, it is:

$ sudo ufw allow from 192.155.13.121 to 1000:2000/tcp

There various protocols available in network but the common ones are:

  • TCP
  • UDP

View The Rules

To view the rules, you can use:

$ sudo ufw status

This will dump the full list, something like:

Status: active
To                    Action     FROM
--                    ------     ----
...                   ...        ...
22                    ALLOW      192.155.13.121

If you want verbose, just add the verbose statement:

$ sudo ufw status verbose

Updating Rules

ufw is smart enough to identify same or new rules. You just need to re-issue the new rules with the same rule statements will do. Example, to set SSH port from allow to deny, the pattern will look like this:

$ sudo ufw allow 22
Rule added
Rule added (v6)
$ sudo ufw allow 22
Skipping adding existing rule
Skipping adding existing rule (v6)
$ sudo ufw deny 22
Rule updated
Rule updated (v6)

Notice that if we issue the same rule for the 2nd time, ufw skips it. However, on the 3rd time, we are updating it from allow to deny access. Hence, ufw updates the rule accordingly.

Deleting Rules

Lastly, to delete rule, you use the delete statements. You can do deletion in 2 ways and we will go through them one by one.


Delete by Rule Statement

The easiest (somehow) way to delete the rule is to write the rule statement for the delete command. The pattern is as follows:

$ sudo delete <STATEMENT>

Example, say we want to delete allowing access to port 22, we write:

$ sudo delete allow port 22

If we want to completely remove it, then just remember to delete deny part as well:

$ sudo delete allow port 22
$ sudo delete deny port 22


Delete by Rule ID

Each applied rules has its own ID. You can actually count it from the status. Example, adding the "ID" into the list:

$ sudo ufw status
Status: active
To                    Action     FROM
--                    ------     ----
22                    ALLOW      anywhere        # ID: 1
22 (v6)               ALLOW      anywhere        # ID: 2

Hence, say we want to delete the rule with ID: 2, we just type in the ID number:

$ sudo ufw delete 2

This deletes that one specific rules. Then the list is reorganized and you need to recount again.

Backing Up Rules

Apparently, ufw does not support backup/export rules in their bug report. Hence, there are various ways to do it like copying from the /lib directory or install another firewall (iptables). However, I find those methods impractical. One easy way is:


Script a BASH Script Executing the Rules

The easiest way to do it is to script a BASH script for the rules. Here is a simple template:

#!/bin/sh
# UFW RULES LIST
#######################################################
# 1. check root privilege                             #
#######################################################
if [ "$(/usr/bin/whoami)" != "root" ]; then
        1>&2 echo "[ ERROR ] not a root user."
        exit 1
fi

if [ -e "/sbin/ufw" ]; then
        alias ufw=/sbin/ufw
fi

#######################################################
# 2. reset ufw so that we can implement all the rules #
#######################################################
echo y | ufw reset
echo y | ufw enable


#######################################################
# 3. set default rules                                #
#######################################################
ufw default deny incoming
ufw default allow outgoing
ufw default deny forward


#######################################################
# 4. set my rules                                     #
#######################################################
ufw allow from 192.168.15.1/24 to any port 22
ufw deny from 192.168.15.33 to any port 22
.. add more rules ...


#######################################################
# 5. set my rules                                     #
#######################################################
ufw status

Hence, you can add your own rules inside #4.

That's all about ufw. It's easier to use right?