UFW Firewall Rules Cheat Sheet for Linux

by Liam Foster
UFW Firewall Rules Cheat Sheet for Linux

UFW (Uncomplicated Firewall) is the default packet filter on Debian and Ubuntu. It wraps iptables with a simpler syntax, but the rules still execute at kernel level—mistakes lock you out. This cheat sheet covers the mental model, the commands, and the failure modes.

The Model: Three Layers

UFW operates in three layers:

  1. State: enabled or disabled. Disabled = no filtering.
  2. Policy: default action for inbound, outbound, and routed traffic (ALLOW, DENY, REJECT).
  3. Rules: specific allow/deny statements, evaluated top-to-bottom, first match wins.

When you enable UFW, it sets a default inbound policy (usually DENY) and outbound (usually ALLOW). Rules are inserted at the top of the chain and take precedence. Think of it as a checklist: "Does this packet match rule 1? No. Rule 2? Yes, ALLOW it." Stop.

Enable and Disable

sudo ufw enable
sudo ufw disable
sudo ufw status
sudo ufw status verbose

status verbose shows rule numbers, which you need for deletion and reordering. Enable UFW after you've added your SSH rule, or you'll lock yourself out.

Allow and Deny Rules

By port number

sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw deny 23/tcp

Always specify the protocol (tcp or udp). If you omit it, both are allowed. Port ranges work too:

sudo ufw allow 6000:6010/tcp

By service name

sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw allow ftp

Service names are looked up in /etc/services. This is readable but risky if the mapping changes; prefer explicit port numbers in production.

By source IP

sudo ufw allow from 192.168.1.0/24 to any port 22
sudo ufw allow from 10.0.0.5 to any port 3306
sudo ufw deny from 192.168.1.100 to any port 80

This is the pattern for "allow SSH only from the office subnet" or "deny a specific IP from HTTP." The to any clause is optional but explicit.

By interface

sudo ufw allow in on eth0 to any port 22
sudo ufw allow out on eth1 to any port 53

Useful for multi-NIC hosts: allow SSH only on the internal interface, deny all on the public one.

Delete and Modify Rules

Delete by rule number

sudo ufw status numbered
sudo ufw delete 3

Always run status numbered first. When you delete a rule, the numbers shift down; delete from highest number first if removing multiple rules.

Delete by rule syntax

sudo ufw delete allow 22/tcp
sudo ufw delete deny from 192.168.1.100

This works if you remember the exact syntax. Easier to mess up than deletion by number.

Insert at a specific position

sudo ufw insert 1 allow 22/tcp

Inserts the rule at position 1, pushing existing rules down. Useful when you need a rule to take precedence before a catch-all deny.

Default Policies

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw default deny routed

The first two are standard. routed applies to traffic forwarded through the host (only relevant on routers or gateways). Most servers use deny routed.

Common Patterns

Lockdown: deny all, allow specific

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

This is the production default. Everything is blocked except SSH, HTTP, and HTTPS.

Allow internal subnet, deny the world

sudo ufw allow from 10.0.0.0/8 to any port 3306
sudo ufw deny 3306/tcp

Order matters. The allow from rule is evaluated first (it was inserted more recently), so MySQL is open to 10.0.0.0/8 and closed to everyone else.

Rate limit (SYN flood protection)

sudo ufw limit 22/tcp

Limits connections to 6 per 30 seconds from the same IP. Good for SSH; don't use on HTTP.

Reject instead of deny

sudo ufw reject 22/tcp

DENY drops packets silently. REJECT sends an ICMP "port unreachable" back. REJECT is slower and more verbose; use it only if you want to signal "this port doesn't exist."

Logging

sudo ufw logging on
sudo ufw logging off
sudo ufw logging high
sudo ufw logging medium
sudo ufw logging low

Logs go to /var/log/ufw.log. High volume can fill the disk; use low on busy production servers. Disable logging unless you're actively debugging.

Reload and Reset

sudo ufw reload

Reloads the ruleset without dropping existing connections. Use this after bulk rule changes.

sudo ufw reset

Deletes all rules and restores defaults. Dangerous on a remote host—you'll lose access.

When This Breaks

Locked out of SSH

You enabled UFW without allowing port 22 first. The only fix is physical access or a rescue console. Always test UFW rules on a non-critical host or in a VM first. If you must enable it remotely, add the SSH rule, enable UFW, then verify you can still log in before doing anything else.

Rules aren't taking effect

Check that UFW is actually enabled: sudo ufw status. A disabled firewall blocks nothing. Also verify the rule syntax: sudo ufw status verbose shows the exact rules in the kernel. If a rule is there but not working, the default policy may be overriding it (check the order with numbered).

Performance degradation

Each rule is a linear lookup. Hundreds of rules slow packet processing. Keep rules under 50 if possible. Use IP ranges and service groups instead of individual rules. For complex filtering, consider nftables or iptables directly (but that's a different tool).

IPv6 leaks

UFW has separate IPv6 rules. If you only add IPv4 rules, IPv6 traffic bypasses them. Check /etc/ufw/ufw.conf and ensure IPV6=yes. Add IPv6 rules explicitly:

sudo ufw allow [::1]/128 port 22

Rule order confusion

New rules are inserted at the top, not appended. allow 22 followed by deny 22 results in the allow taking precedence. Use insert to be explicit about position, or delete and re-add in the correct order.

Trade-offs

UFW is simple to learn but opaque compared to raw iptables. You can't see the full rule expansion or debug complex chains easily. For a single-purpose server (web, database, cache), UFW is sufficient. For complex routing or stateful filtering on many interfaces, you'll outgrow it and need iptables or nftables.

UFW also doesn't handle application-layer filtering. A port 80 allow rule permits any HTTP traffic, malformed or not. For DDoS mitigation or protocol-aware filtering, add a WAF or load balancer upstream. If you're running a headless storefront on a tight budget, locking down your server with UFW before exposing any public endpoints is especially important.

Takeaway

UFW is a checklist for packets: enable it, set a default deny policy, allow what you need, and test on a non-critical host first. The three-layer model (state, policy, rules) is all you need to reason about any configuration. Always add SSH before enabling, verify you can still log in, then move on.