You probably think of iptables as the "real" Linux firewall and ufw as the "easy" one. The surprising truth is that ufw is iptables, just wrapped in a much more user-friendly interface.

Let’s see ufw in action. Imagine you want to allow SSH traffic (port 22) from anywhere on your server, and HTTP (port 80) and HTTPS (port 443) only from a specific IP address, say 192.168.1.100.

First, ensure ufw is installed. On Debian/Ubuntu:

sudo apt update && sudo apt install ufw

Then, enable it:

sudo ufw enable

Now, add your rules:

sudo ufw allow ssh
sudo ufw allow from 192.168.1.100 to any port 80,443

Finally, check the status:

sudo ufw status verbose

You’ll see output like this:

Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       Anywhere
80,443/tcp                 ALLOW       192.168.1.100
22/tcp (v6)                ALLOW       Anywhere (v6)
80,443/tcp (v6)            ALLOW       192.168.1.100 (v6)

This looks simple, right? ufw hides the complexity of iptables chains, tables, and packet matching.

The core problem ufw solves is the steep learning curve of iptables. iptables operates on a low level, requiring you to understand concepts like:

  • Tables: filter (for packet filtering), nat (for Network Address Translation), mangle (for modifying packet headers).
  • Chains: INPUT (for packets destined for the local machine), OUTPUT (for packets originating from the local machine), FORWARD (for packets passing through the machine).
  • Rules: Specific criteria (source/destination IP, port, protocol) and actions (ACCEPT, DROP, REJECT).
  • Policy: The default action for a chain if no rule matches.

ufw abstracts all of this. When you run sudo ufw allow ssh, it translates this into specific iptables commands for the filter table, INPUT chain. The allow action becomes ACCEPT, and ssh is resolved to its default port 22/tcp. Similarly, allow from 192.168.1.100 to any port 80,443 generates rules targeting the INPUT chain with specific source and destination port matches.

The default ufw policy is to deny incoming traffic and allow outgoing traffic. This is a secure default: you explicitly allow what you want to let in, and everything else is blocked.

You can also manage ufw more granularly. For instance, to limit connection rates for SSH to prevent brute-force attacks:

sudo ufw limit ssh

This translates to an iptables rule that uses the limit module, allowing a certain number of packets per unit of time and then rate-limiting subsequent packets.

The default ufw configuration uses the iptables filter table. However, ufw can also manage rules for other iptables tables, though this is less common for basic use cases. You can add custom iptables rules directly by editing /etc/ufw/before.rules and /etc/ufw/after.rules. These files are processed by ufw before and after its own rules, respectively.

For example, if you needed to do NAT (which is typically handled by the nat table in iptables), you would configure it in /etc/ufw/before.rules or /etc/ufw/before6.rules for IPv6. A common scenario is masquerading outgoing traffic from a private network. You’d add something like this to /etc/ufw/before.rules:

*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE
COMMIT

Here, -s 192.168.1.0/24 specifies the private network, -o eth0 the external interface, and -j MASQUERADE tells iptables to rewrite the source IP address to that of eth0. ufw itself doesn’t have a direct command for MASQUERADE, hence the need to drop down to raw iptables syntax within its configuration files.

Most users will never need to touch iptables directly when using ufw. ufw provides a clear, concise way to define common firewall policies. However, understanding that ufw is merely a frontend for iptables is crucial when you encounter complex networking requirements or need to debug intricate firewall behaviors.

The next step after mastering ufw is understanding how to integrate it with other network services or how to manage stateful firewalling more deeply.

Want structured learning?

Take the full Iptables course →