Quick Answer:
ufw enableturns on the firewall.ufw allow 22allows SSH.ufw allow 80,443/tcpallows web traffic.ufw deny 3306blocks MySQL.ufw statusshows active rules.ufw delete allow 80removes a rule.
Need a VPS? Vultr (free credit), DigitalOcean ($200 free credit), or RackNerd (cheap annual deals).
Enable and Status
# Install (usually pre-installed on Ubuntu)
apt install ufw -y
# Enable firewall
ufw enable
# Disable firewall
ufw disable
# Check status
ufw status
ufw status verbose # With default policies
ufw status numbered # With rule numbers (for deleting)
# Reset all rules (careful!)
ufw reset
Allow Rules
# Allow a port (TCP + UDP)
ufw allow 22
# Allow specific protocol
ufw allow 80/tcp
ufw allow 53/udp
# Allow multiple ports
ufw allow 80,443/tcp
# Allow port range
ufw allow 8000:8100/tcp
# Allow from specific IP
ufw allow from 10.0.0.5
# Allow from specific IP to specific port
ufw allow from 10.0.0.5 to any port 3306
# Allow from subnet
ufw allow from 192.168.1.0/24
# Allow from subnet to specific port
ufw allow from 192.168.1.0/24 to any port 22
# Allow to specific interface
ufw allow in on eth0 to any port 80
Deny and Block
# Deny a port
ufw deny 23 # Telnet
ufw deny 3306 # MySQL from outside
# Deny from specific IP
ufw deny from 1.2.3.4
# Deny from subnet
ufw deny from 10.0.0.0/8
# Reject (sends error back, unlike deny which silently drops)
ufw reject 23
Delete Rules
# Delete by rule
ufw delete allow 80
# Delete by rule number
ufw status numbered # See numbers first
ufw delete 3 # Delete rule #3
# Delete deny rule
ufw delete deny from 1.2.3.4
Default Policies
# Deny all incoming (recommended)
ufw default deny incoming
# Allow all outgoing
ufw default allow outgoing
# Deny forwarding
ufw default deny routed
# View current defaults
ufw status verbose
Common Server Setup
Web Server
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp # SSH
ufw allow 80/tcp # HTTP
ufw allow 443/tcp # HTTPS
ufw enable
Database Server
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow from 10.0.0.0/24 to any port 3306 # MySQL from local network only
ufw allow from 10.0.0.0/24 to any port 5432 # PostgreSQL from local network only
ufw enable
VPN Server (WireGuard)
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 51820/udp # WireGuard
ufw enable
Proxy Server (3X-UI)
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 443/tcp # VLESS-WS
ufw allow 8443/tcp # Reality
ufw allow 2053/tcp # Panel
ufw allow 2082,2083/tcp # CDN ports
ufw allow 8880/tcp # CDN HTTP
ufw enable
Application Profiles
# List available profiles
ufw app list
# View profile details
ufw app info "Nginx Full"
# Allow by profile
ufw allow "Nginx Full" # 80 + 443
ufw allow "Nginx HTTP" # 80 only
ufw allow "Nginx HTTPS" # 443 only
ufw allow "OpenSSH" # 22
# Common profiles
# Nginx Full = 80,443/tcp
# Nginx HTTP = 80/tcp
# Nginx HTTPS = 443/tcp
# OpenSSH = 22/tcp
# Apache Full = 80,443/tcp
Create Custom Profile
Create /etc/ufw/applications.d/myapp:
[MyApp]
title=My Application
description=Custom web application
ports=3000/tcp|8080/tcp
Then: ufw allow "MyApp"
Logging
# Enable logging
ufw logging on
# Logging levels
ufw logging low # Only blocked
ufw logging medium # Blocked + allowed (if policy matched)
ufw logging high # All packets
ufw logging full # Everything
# View firewall logs
grep "UFW" /var/log/syslog | tail -20
journalctl | grep "UFW" | tail -20
# Disable logging
ufw logging off
Rate Limiting
# Rate limit SSH (6 connections per 30 seconds per IP)
ufw limit 22/tcp
# This blocks IPs that attempt more than 6 connections in 30 seconds
# Much simpler than iptables rate limiting
Forwarding (NAT)
To use UFW for routing/NAT (e.g., VPN server):
Edit /etc/ufw/sysctl.conf:
net/ipv4/ip_forward=1
Edit /etc/ufw/before.rules — add before the *filter line:
*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 10.66.66.0/24 -o eth0 -j MASQUERADE
COMMIT
Edit /etc/default/ufw:
DEFAULT_FORWARD_POLICY="ACCEPT"
Then: ufw reload
Insert Rules (Order Matters)
# Insert at specific position (rules are processed top to bottom)
ufw insert 1 allow from 10.0.0.5 # Make this the first rule
# Example: allow one IP but block its subnet
ufw insert 1 allow from 10.0.0.5
ufw insert 2 deny from 10.0.0.0/24
UFW vs iptables
| UFW | iptables | |
|---|---|---|
| Difficulty | Easy | Hard |
| Best for | Quick server setup | Complex rules, NAT, advanced filtering |
| Rate limiting | Basic (limit command) | Advanced (per-second, per-minute) |
| Logging | Simple on/off | Granular per-rule |
| NAT | Possible but manual | Native support |
| Under the hood | Generates iptables rules | Direct kernel firewall |
UFW is a frontend for iptables. When you run ufw allow 22, it creates the equivalent iptables rule. For 90% of servers, UFW is all you need.
Quick Troubleshooting
# Can't SSH after enabling UFW?
# Boot into recovery mode or use console access, then:
ufw allow 22
ufw enable
# Check if UFW is actually active
ufw status
# See generated iptables rules
iptables -L -n
# Port open in UFW but still can't connect?
# Check if service is actually listening:
ss -tlnp | grep :80
# Check if another firewall (cloud provider) is blocking:
# AWS: Security Groups
# GCP: VPC Firewall Rules
# Azure: NSG