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.
UFW vs iptables vs firewalld vs nftables
Before diving in, understand where UFW sits in the Linux firewall stack:
| Tool | Default on | Complexity | Best for |
|---|---|---|---|
| UFW | Ubuntu, Debian, Mint | Simple | Desktops, simple servers, fast setup |
| firewalld | Fedora, RHEL, AlmaLinux, Rocky | Medium | Enterprise Linux, zone-based policy |
| iptables | All distros (legacy) | Complex | Fine-grained rules, scripting, compatibility |
| nftables | All modern distros | Complex | Modern 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+)
sudoprivileges- 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 -yCheck the current status before touching anything:
sudo ufw status verboseStatus: inactiveUFW 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/tcpStep 3: Enable the Firewall
sudo ufw enableCommand may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startupUFW is now active and will persist across reboots via a systemd service (ufw.service). Verify:
sudo ufw status verboseStatus: 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/tcpBy 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.22Specifying 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 tcpRate 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/udpThis 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 listAvailable 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 HTTPSTo 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/tcpsudo ufw app update MyApp
sudo ufw allow MyAppManaging and Auditing Rules
# List rules with line numbers (use this before deleting)
sudo ufw status numberedStatus: 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 resetLogging
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.logA 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=0The 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/ufwIPV6=yesIf it shows no, edit the file and reload:
sudo nano /etc/default/ufw
# Set IPV6=yes
sudo ufw reloadWith 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 verboseDatabase 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 enableMail 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 # POP3SVPN 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.rulesTroubleshooting
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 reloadIf 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 :
Further Reading
