Skip to content

UFW Firewall Management

UFW (Uncomplicated Firewall) is the standard firewall tool on Ubuntu. It wraps iptables/nftables into something you can actually manage without losing your mind. This covers the syntax and patterns I use across the MajorsHouse fleet.

The Short Answer

# Enable UFW
sudo ufw enable

# Allow a port
sudo ufw allow 80

# Block a specific IP
sudo ufw insert 1 deny from 203.0.113.50

# Check status
sudo ufw status numbered

Basic Rules

Allow by Port

# Allow HTTP and HTTPS
sudo ufw allow 80
sudo ufw allow 443

# Allow a port range
sudo ufw allow 6000:6010/tcp

# Allow a named application profile
sudo ufw allow 'Apache Full'

Allow by Interface

Useful when you only want traffic on a specific network interface — this is how SSH is restricted to Tailscale across the fleet:

# Allow SSH only on the Tailscale interface
sudo ufw allow in on tailscale0 to any port 22

# Then deny SSH globally (evaluated after the allow above)
sudo ufw deny 22

Rule order matters. UFW evaluates rules top to bottom and stops at the first match.

Allow by Source IP

# Allow a specific IP to access SSH
sudo ufw allow from <tailscale-ip> to any port 22

# Allow a subnet
sudo ufw allow from 192.168.50.0/24 to any port 22

Blocking IPs

Insert Rules at the Top

When blocking IPs, use insert 1 to place the deny rule at the top of the chain. Otherwise it may never be evaluated because an earlier ALLOW rule matches first.

# Block a single IP
sudo ufw insert 1 deny from 203.0.113.50

# Block a subnet
sudo ufw insert 1 deny from 203.0.113.0/24

# Block an IP from a specific port only
sudo ufw insert 1 deny from 203.0.113.50 to any port 443

Don't Accumulate Manual Blocks

Manual ufw deny rules pile up fast. On one of my servers, I found 30,142 manual DENY rules — a 3 MB rules file that every packet had to traverse. Use Fail2ban for automated blocking instead. It manages bans with expiry and doesn't pollute your UFW rules.

If you inherit a server with thousands of manual blocks:

ufw --force reset will lock you out — read this before running it — corrected 2026-07-20

The reset wipes all rules, and the re-add block below only restores three. That is not the real rule set on any fleet host. Verified live on teelia 2026-07-20, its actual UFW rules are:

2222/tcp            ← sshd is on 2222, NOT 22. Resetting to "deny 22" locks SSH out entirely.
10050               ← Zabbix agent
6514                ← syslog over TLS
ALLOW from 167.71.189.160, 162.243.188.66   ← two trusted source IPs
80/tcp, 443/tcp
22 on tailscale0

The reset block destroys 2222, 10050, 6514, and both allow-from rules — and on teelia (Tailscale-SSH, no console fallback beyond DO) that means lockout. Never run this without first capturing the current rules and re-adding every one:

ufw status numbered > ~/ufw-rules-backup-$(date +%F).txt   # capture FIRST

A targeted delete of the manual DENY rules (see Delete Rules below) is almost always better than a full reset. If you must reset, rebuild from the backup, not from the three-line block.

# Nuclear option — DANGEROUS, see callout above. Re-add EVERY rule the host needs,
# not just these three. Ports/allow-froms are per-host; check `ufw status numbered` first.
sudo ufw status numbered > ~/ufw-rules-backup-$(date +%F).txt
sudo ufw --force reset
# ...then re-add from the backup, e.g. (teelia example — yours will differ):
sudo ufw allow 'Apache Full'
sudo ufw allow 2222/tcp
sudo ufw allow in on tailscale0 to any port 22
# + 10050, 6514, trusted source IPs, etc. — whatever the backup shows
sudo ufw enable

Managing Rules

View Rules

# Simple view
sudo ufw status

# Numbered (needed for deletion and insert position)
sudo ufw status numbered

# Verbose (shows default policies and logging)
sudo ufw status verbose

Delete Rules

# Delete by rule number
sudo ufw delete 3

# Delete by rule specification
sudo ufw delete allow 8080

Default Policies

# Deny all incoming, allow all outgoing (recommended baseline)
sudo ufw default deny incoming
sudo ufw default allow outgoing

Don't Forget Web Server Ports

If you're running a web server behind UFW, make sure ports 80 and 443 are explicitly allowed. This sounds obvious, but it's easy to miss — especially on servers where UFW was enabled after the web server was already running, or where a firewall reset dropped rules that were never persisted.

# Allow HTTP and HTTPS
sudo ufw allow 80
sudo ufw allow 443

# Or use an application profile
sudo ufw allow 'Apache Full'

If your site suddenly stops responding after enabling UFW or resetting rules, check sudo ufw status numbered first. Missing web ports is the most common cause.

UFW with Fail2ban

On Ubuntu servers, Fail2ban and UFW operate at different layers. Fail2ban typically creates its own nftables table (inet f2b-table) at a higher priority than UFW's chains. This means:

  • Fail2ban bans take effect before UFW rules are evaluated
  • A banned IP is rejected even if UFW has an ALLOW rule for that port
  • Add trusted IPs (your own, monitoring, etc.) to ignoreip in /etc/fail2ban/jail.local to prevent self-lockout
# /etc/fail2ban/jail.local
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 100.64.0.0/10

Tailscale's CGNAT range is 100.64.0.0/10 (100.64.0.0–100.127.255.255) — use exactly that to whitelist fleet traffic.

Do NOT use 100.0.0.0/8 — corrected 2026-07-20

An earlier version of this article showed ignoreip = 127.0.0.1/8 ::1 100.0.0.0/8. /8 is four times too wide — it whitelists 100.0.0.0–100.63.255.255 (~4 million routable public addresses outside Tailscale's range) from every fail2ban jail, so a brute-force from any of those IPs is never banned.

Verified 2026-07-20: every fleet host is already correct (100.64.0.0/10) — dcaprod, majorlinux, tttpod, majortoot, teelia all use the /10. The /8 never made it into production; this was a documentation defect only. But anyone copying the old block would have introduced the hole, so it is fixed here.

UFW Logging

# Enable logging (low/medium/high/full)
sudo ufw logging medium

Logs go to /var/log/ufw.log. Useful for seeing what's getting blocked, but medium or low is usually enough — high and full can be noisy.

Fleet Reference

UFW is used on these MajorsHouse servers:

Host Key UFW Rules
majortoot SSH on tailscale0, deny 22 globally
majorlinux SSH on tailscale0, deny 22 globally
tttpod SSH on tailscale0, deny 22 globally, Apache Full (added 2026-04-03)
teelia SSH on tailscale0, deny 22 globally, Apache Full

The Fedora servers (majorlab, majorhome, majormail, majordiscord) use iptables or firewalld instead.

See Also