UFW Firewall: Complete Linux Guide

Tested on: Ubuntu 26.04 LTS · Debian 12 · Linux Mint 22 — Last updated: June 2026

UFW (Uncomplicated Firewall) is the default firewall management tool on Ubuntu and Debian-based distributions. It wraps iptables and nftables in a consistent, human-readable CLI — giving you a working firewall in minutes without memorizing kernel netfilter syntax. This guide covers everything from first-time setup to production server configurations, rate limiting, application profiles, and debugging blocked connections.

Contents
  1. UFW vs iptables vs firewalld vs nftables
  2. Prerequisites
  3. Install and Enable UFW
    1. Step 1: Set Default Policies
    2. Step 2: Allow SSH Before Enabling
    3. Step 3: Enable the Firewall
  4. Allow and Deny Rules
    1. By Service Name
    2. By Port Number and Protocol
    3. By IP Address and Subnet
    4. Specifying Network Interface
  5. Rate Limiting — Brute Force Protection
  6. UFW Application Profiles
  7. Managing and Auditing Rules
  8. Logging
  9. IPv6 Support
  10. Common Production Configurations
    1. Web Server (Nginx or Apache)
    2. Database Server (internal access only)
    3. Mail Server
    4. VPN Gateway (WireGuard)
  11. Troubleshooting
    1. Locked out of SSH after enabling UFW
    2. Further Reading

UFW vs iptables vs firewalld vs nftables

Before diving in, understand where UFW sits in the Linux firewall stack:

ToolDefault onComplexityBest for
UFWUbuntu, Debian, MintSimpleDesktops, simple servers, fast setup
firewalldFedora, RHEL, AlmaLinux, RockyMediumEnterprise Linux, zone-based policy
iptablesAll distros (legacy)ComplexFine-grained rules, scripting, compatibility
nftablesAll modern distrosComplexModern replacement for iptables, better performance

UFW does not replace the kernel's netfilter — it generates iptables or nftables rules under the hood. You can verify this at any time by running sudo iptables -L -n -v alongside UFW. On Ubuntu 24.04 and later, UFW defaults to nftables as its backend. UFW is not available by default on Fedora or RHEL-based systems — use firewalld there.

Prerequisites

  • A Debian-based Linux system (Ubuntu 24.04+, Debian 13+, Linux Mint 22.3+)
  • sudo privileges
  • If managing a remote server: console or out-of-band access in case you lock yourself out of SSH (your VPS provider's web console covers this)
  • Basic familiarity with TCP/IP port concepts

Install and Enable UFW

UFW is pre-installed on Ubuntu. On a minimal Debian install you may need to install it:

sudo apt update && sudo apt install ufw -y

Check the current status before touching anything:

sudo ufw status verbose
Status: inactive

UFW ships disabled. Do not enable it yet — set your rules first.

Step 1: Set Default Policies

Default policies define what happens to connections that don't match any explicit rule. For any internet-facing server, start with these:

sudo ufw default deny incoming    # Block all inbound traffic unless explicitly allowed
sudo ufw default allow outgoing   # Allow all outbound traffic
sudo ufw default deny forward     # Disable packet forwarding (enable only for routers/VPNs)

These three commands are the foundation. Everything you allow from here is an explicit exception to the deny-by-default posture.

Step 2: Allow SSH Before Enabling

This is the most critical step if you're on a remote server. Enable UFW without doing this first and you will be locked out:

# Allow SSH using the service name (resolves to port 22/tcp)
sudo ufw allow ssh

# If you've moved SSH to a non-standard port, use the port number instead:
sudo ufw allow 2222/tcp

Step 3: Enable the Firewall

sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

UFW is now active and will persist across reboots via a systemd service (ufw.service). Verify:

sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (forward)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW IN    Anywhere
22/tcp (v6)                ALLOW IN    Anywhere (v6)

Allow and Deny Rules

By Service Name

UFW understands common service names from /etc/services:

sudo ufw allow ssh        # port 22/tcp
sudo ufw allow http       # port 80/tcp
sudo ufw allow https      # port 443/tcp
sudo ufw allow ftp        # port 21/tcp
sudo ufw allow samba      # ports 137,138/udp + 139,445/tcp

By Port Number and Protocol

# Single TCP port
sudo ufw allow 8080/tcp

# Single UDP port (e.g., OpenVPN)
sudo ufw allow 1194/udp

# Port range (e.g., passive FTP)
sudo ufw allow 49152:65535/tcp

# Deny a port explicitly
sudo ufw deny 23/tcp      # Block Telnet
sudo ufw deny 3389/tcp    # Block RDP from everywhere (before adding specific allow)

By IP Address and Subnet

# Allow all traffic from a trusted IP
sudo ufw allow from 203.0.113.50

# Allow a specific IP to reach a specific port only
sudo ufw allow from 10.0.0.5 to any port 5432 proto tcp    # PostgreSQL from one host

# Allow an entire subnet (e.g., internal network to MySQL)
sudo ufw allow from 192.168.1.0/24 to any port 3306 proto tcp

# Deny a specific IP (useful for blocking known bad actors)
sudo ufw deny from 198.51.100.22

Specifying Network Interface

On servers with multiple interfaces (e.g., a public eth0 and a private eth1), you can scope rules to a specific interface:

# Allow HTTP only on the public interface
sudo ufw allow in on eth0 to any port 80 proto tcp

# Allow MySQL only on the private interface
sudo ufw allow in on eth1 to any port 3306 proto tcp

Rate Limiting — Brute Force Protection

UFW's built-in rate limiting drops connections from any IP that makes more than 6 new connections within 30 seconds. Apply it to every authentication service exposed to the internet:

# Rate-limit SSH (standard port)
sudo ufw limit ssh

# Rate-limit a custom SSH port
sudo ufw limit 2222/tcp

# Rate-limit any port (e.g., a VPN endpoint)
sudo ufw limit 1194/udp

This is not a substitute for fail2ban or key-based authentication — use all three together. Rate limiting handles volumetric brute force; fail2ban handles persistent low-and-slow attempts; key-based auth means stolen passwords don't matter.

UFW Application Profiles

Applications can ship UFW profiles in /etc/ufw/applications.d/ that bundle their required ports under a readable name. Nginx and Apache both register profiles on install:

# List all registered profiles
sudo ufw app list
Available applications:
  Nginx Full
  Nginx HTTP
  Nginx HTTPS
  OpenSSH
# Inspect what ports a profile covers
sudo ufw app info 'Nginx Full'
Profile: Nginx Full
Title: Web Server (Nginx, HTTP + HTTPS)
Description: Small, but very powerful and efficient web server

Ports:
  80,443/tcp
# Apply profiles
sudo ufw allow 'Nginx Full'     # Opens 80 and 443
sudo ufw allow 'Nginx HTTPS'    # Opens 443 only (after obtaining a cert)
sudo ufw delete allow 'Nginx HTTP'    # Remove HTTP after forcing HTTPS

To write your own application profile — useful for custom services:

sudo nano /etc/ufw/applications.d/myapp
[MyApp]
title=My Custom Application
description=API server running on port 9000
ports=9000/tcp
sudo ufw app update MyApp
sudo ufw allow MyApp

Managing and Auditing Rules

# List rules with line numbers (use this before deleting)
sudo ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22/tcp                     ALLOW IN    Anywhere
[ 2] 80/tcp                     ALLOW IN    Anywhere
[ 3] 443/tcp                    ALLOW IN    Anywhere
[ 4] 8080/tcp                   ALLOW IN    Anywhere
[ 5] 22/tcp (v6)                ALLOW IN    Anywhere (v6)
# Delete rule by number (most reliable method)
sudo ufw delete 4

# Delete rule by specification
sudo ufw delete allow 8080/tcp

# Reload rules without disabling UFW
sudo ufw reload

# Disable UFW temporarily (rules preserved, firewall inactive)
sudo ufw disable

# Full reset — disables UFW and wipes all rules
sudo ufw reset

Logging

UFW logging is essential for diagnosing blocked connections and auditing access:

# Enable logging (off by default on some installs)
sudo ufw logging on

# Set log level: low | medium | high | full
# low = blocked packets only (recommended starting point)
# medium = blocked + allowed packets not matching rules
# high = all packets
sudo ufw logging medium

# Follow the log in real time
sudo journalctl -f | grep UFW

# Or on systems with syslog:
sudo tail -f /var/log/ufw.log

A typical blocked packet entry looks like:

Jun 15 03:21:44 srv1 kernel: [UFW BLOCK] IN=eth0 OUT= MAC=... SRC=198.51.100.9 DST=203.0.113.1 LEN=44 TOS=0x00 PREC=0x00 TTL=241 ID=54321 PROTO=TCP SPT=45982 DPT=23 WINDOW=1024 RES=0x00 SYN URGP=0

The key fields: SRC (source IP), DPT (destination port), PROTO (protocol). Use this to identify misconfigured rules or active scan traffic.

IPv6 Support

UFW handles IPv4 and IPv6 simultaneously. Confirm IPv6 is enabled in the UFW config:

grep IPV6 /etc/default/ufw
IPV6=yes

If it shows no, edit the file and reload:

sudo nano /etc/default/ufw
# Set IPV6=yes
sudo ufw reload

With IPv6 enabled, every rule you add automatically creates a matching IPv6 rule. The ufw status numbered output shows both the IPv4 and (v6) variants.

Common Production Configurations

Web Server (Nginx or Apache)

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw limit ssh
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw status verbose

Database Server (internal access only)

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw limit ssh
sudo ufw allow from 10.0.0.0/8 to any port 5432 proto tcp    # PostgreSQL from private network only
sudo ufw allow from 10.0.0.0/8 to any port 3306 proto tcp    # MySQL/MariaDB
sudo ufw enable

Mail Server

sudo ufw allow 25/tcp     # SMTP (inbound mail)
sudo ufw allow 587/tcp    # Submission (authenticated outbound)
sudo ufw allow 465/tcp    # SMTPS (legacy SSL)
sudo ufw allow 143/tcp    # IMAP
sudo ufw allow 993/tcp    # IMAPS
sudo ufw allow 110/tcp    # POP3
sudo ufw allow 995/tcp    # POP3S

VPN Gateway (WireGuard)

sudo ufw allow 51820/udp          # WireGuard
sudo ufw default allow forward    # Enable forwarding for VPN clients

# Also edit /etc/default/ufw to set DEFAULT_FORWARD_POLICY="ACCEPT"
# and add NAT rules to /etc/ufw/before.rules

Troubleshooting

Locked out of SSH after enabling UFW

Access your VPS provider's web console (DigitalOcean calls it "Console", Hetzner calls it "VNC Console"). From there, the server is local — SSH rules don't apply:

sudo ufw allow ssh
sudo ufw reload

If the console shows UFW is active but you still can't reach SSH, check that sshd is actually running and listening:

sudo systemctl status ssh
ss -tlnp | grep :


Go up

This site uses cookies for analytics and advertising (Google AdSense). By continuing to browse, you accept our use of cookies. Learn more