What Is UFW?
UFW (Uncomplicated Firewall) is a user-friendly front end for managing iptables firewall rules on Ubuntu and other Debian-based distributions. While iptables is powerful, its syntax is complex and error-prone. UFW provides a simplified command-line interface that makes it straightforward to create and manage firewall rules without deep knowledge of iptables chains and tables.
UFW is pre-installed on Ubuntu but disabled by default. Enabling it with sensible default policies is one of the first steps in any Linux security checklist. This guide covers every common UFW operation, from basic setup to advanced configurations.
Enabling and Disabling UFW
Before enabling UFW, always add a rule to allow SSH. If you enable UFW with a default-deny policy without allowing SSH, you will be locked out of a remote server:
# Allow SSH before enabling (critical for remote servers)
sudo ufw allow ssh
# Enable UFW
sudo ufw enable
# Disable UFW (if needed)
sudo ufw disable
# Reset UFW to factory defaults (removes all rules)
sudo ufw reset
When you run ufw enable, the firewall starts immediately and persists across reboots. The ufw reset command removes all rules and disables the firewall — use it only when you want to start over.
Setting Default Policies
Default policies determine what happens to traffic that does not match any explicit rule. The recommended configuration for a server is to deny all incoming traffic and allow all outgoing traffic:
# Deny all incoming connections by default
sudo ufw default deny incoming
# Allow all outgoing connections by default
sudo ufw default allow outgoing
With this configuration, no one can connect to your server unless you explicitly allow it. Your server can still initiate outgoing connections (apt updates, DNS lookups, sending email, etc.).
For high-security environments, you can also restrict outgoing traffic:
sudo ufw default deny outgoing
# Then explicitly allow what's needed
sudo ufw allow out 53 # DNS
sudo ufw allow out 80/tcp # HTTP (for apt)
sudo ufw allow out 443/tcp # HTTPS
sudo ufw allow out 123/udp # NTP
Allowing and Denying Ports
Allow by Port Number
# Allow a specific TCP port
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Allow a specific UDP port
sudo ufw allow 53/udp
# Allow both TCP and UDP
sudo ufw allow 53
# Allow a port range
sudo ufw allow 6000:6007/tcp
Deny a Port
# Deny a specific port (with default deny, this is usually unnecessary
# unless you want to explicitly block something that a later rule might allow)
sudo ufw deny 23/tcp
# Reject instead of deny (sends ICMP unreachable back to sender)
sudo ufw reject 23/tcp
The difference between deny and reject: deny silently drops the packet (the sender gets no response and eventually times out). reject sends an ICMP response telling the sender the port is unreachable. For internet-facing servers, deny is generally preferred because it reveals less information to port scanners.
Allow by Service Name
UFW knows 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 smtp # Port 25/tcp
Allowing Specific IP Addresses
For services that should only be accessed from specific hosts (like a database or admin panel), restrict by source IP:
# Allow all traffic from a specific IP
sudo ufw allow from 203.0.113.50
# Allow a specific IP to a specific port
sudo ufw allow from 203.0.113.50 to any port 3306
# Allow a subnet
sudo ufw allow from 10.0.0.0/24
# Allow a subnet to a specific port
sudo ufw allow from 10.0.0.0/24 to any port 22 proto tcp
Deny a Specific IP
# Block all traffic from a specific IP
sudo ufw deny from 198.51.100.23
# Block a subnet
sudo ufw deny from 198.51.100.0/24
Deleting Rules
There are two ways to delete rules: by rule specification or by rule number.
Delete by Rule Specification
# Delete the exact rule
sudo ufw delete allow 80/tcp
sudo ufw delete allow from 203.0.113.50
sudo ufw delete deny 23/tcp
Delete by Number
# List rules with numbers
sudo ufw status numbered
# Output example:
# [ 1] 22/tcp ALLOW IN Anywhere
# [ 2] 80/tcp ALLOW IN Anywhere
# [ 3] 443/tcp ALLOW IN Anywhere
# Delete rule number 2
sudo ufw delete 2
When deleting by number, note that rule numbers shift after each deletion. If you need to delete multiple rules, start from the highest number and work down, or re-check ufw status numbered after each deletion.
Numbered Rules and Rule Ordering
UFW processes rules in order — the first matching rule wins. This matters when you have both allow and deny rules that might overlap. You can insert rules at specific positions:
# Insert a deny rule at position 1 (before all other rules)
sudo ufw insert 1 deny from 198.51.100.23
# Insert an allow rule at position 2
sudo ufw insert 2 allow from 203.0.113.50 to any port 22
Use ufw status numbered to verify rule order after inserting.
Application Profiles
UFW supports application profiles — predefined rule sets for common applications. Applications register their profiles in /etc/ufw/applications.d/:
# List available application profiles
sudo ufw app list
# Output example:
# Available applications:
# Nginx Full
# Nginx HTTP
# Nginx HTTPS
# OpenSSH
# Apache
# Apache Full
# Apache Secure
# Get info about a profile
sudo ufw app info "Nginx Full"
# Output: ports 80,443/tcp
# Allow using an application profile
sudo ufw allow "Nginx Full"
sudo ufw allow "OpenSSH"
Application profiles simplify management — instead of remembering port numbers, you reference the application name. Packages like Nginx and Apache install their own UFW profiles automatically.
Creating Custom Application Profiles
# /etc/ufw/applications.d/myapp
[MyApp]
title=My Custom Application
description=Custom application running on ports 8080 and 8443
ports=8080,8443/tcp
After creating the file, run sudo ufw app update MyApp to register it.
Logging
UFW logging records firewall activity to syslog. This is invaluable for detecting port scans, brute force attempts, and other suspicious network activity.
# Enable logging
sudo ufw logging on
# Set logging level (off, low, medium, high, full)
sudo ufw logging medium
Logging levels:
- low: Logs blocked packets that do not match a rule (default deny), and packets matching logged rules.
- medium: Adds logging of invalid packets, new connections, and rate-limited logging.
- high: Logs all packets (with rate limiting) — useful for debugging but generates high volume.
- full: Logs every single packet without rate limiting. Only use temporarily for debugging.
Logs are written to /var/log/ufw.log (on most Ubuntu systems). Monitor them for patterns:
# View recent UFW blocks
sudo tail -50 /var/log/ufw.log
# Count blocks by source IP
sudo grep "UFW BLOCK" /var/log/ufw.log | awk '{print $12}' | sort | uniq -c | sort -rn | head -20
Checking Status
# Basic status
sudo ufw status
# Verbose status (shows defaults, logging level, and rules)
sudo ufw status verbose
# Numbered rules
sudo ufw status numbered
The verbose output shows default policies, which is important for understanding how traffic not matching any rule is handled.
Common Server Configurations
Web Server (Nginx/Apache)
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
Database Server (MySQL/PostgreSQL)
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow from 10.0.0.0/24 to any port 22 # SSH from internal only
sudo ufw allow from 10.0.0.0/24 to any port 3306 # MySQL from internal only
sudo ufw enable
Mail Server
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 25/tcp # SMTP
sudo ufw allow 587/tcp # Submission
sudo ufw allow 993/tcp # IMAPS
sudo ufw allow 995/tcp # POP3S
sudo ufw enable
UFW and Docker
Docker modifies iptables rules directly, bypassing UFW entirely. This means Docker-published ports are accessible even if UFW has a default deny policy. This is a common and dangerous misconfiguration. To address it:
# Option 1: Bind Docker containers to localhost only
# In docker-compose.yml:
ports:
- "127.0.0.1:8080:80"
# Option 2: Disable Docker's iptables management
# In /etc/docker/daemon.json:
{
"iptables": false
}
If you disable Docker's iptables management, you must manually configure routing for Docker containers.
Build a Complete Network Defense
A host-based firewall like UFW is essential, but it is one component of a layered security strategy. Combine UFW with SSH hardening, iptables rules for advanced filtering, and edge-level protection from a web application firewall to defend against both network and application-layer threats. Explore NOC.org's security solutions to protect your infrastructure at every layer.