UFW Configuration¶
Rule Syntax¶
Allow Rules¶
# Allow by port
sudo ufw allow 22
sudo ufw allow 22/tcp
sudo ufw allow 22/udp
# Allow by service name
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
# Allow port range
sudo ufw allow 6000:6100/tcp
# Allow by app profile
sudo ufw allow OpenSSH
sudo ufw allow 'Apache Full'
Deny Rules¶
# Deny port
sudo ufw deny 23
# Deny from IP
sudo ufw deny from 10.0.0.0/8
# Deny specific combination
sudo ufw deny from 192.168.1.100 to any port 22
Reject Rules¶
Reject sends an ICMP unreachable (client knows immediately):
Limit Rules¶
Rate limits connections (6 connections per 30 seconds):
Advanced Rule Syntax¶
Source and Destination¶
# From specific IP
sudo ufw allow from 192.168.1.100
# From subnet
sudo ufw allow from 192.168.1.0/24
# To specific port from specific IP
sudo ufw allow from 192.168.1.100 to any port 22
# From any to specific destination
sudo ufw allow from any to 192.168.1.100 port 80
Interface Restrictions¶
# Allow on specific interface
sudo ufw allow in on eth0 to any port 80
sudo ufw allow in on virbr0
# Output interface
sudo ufw allow out on eth0 to any port 443
Protocol Specification¶
# TCP only
sudo ufw allow 80/tcp
# UDP only
sudo ufw allow 53/udp
# Both (default)
sudo ufw allow 80
Comments¶
# Add comment to rule
sudo ufw allow 22/tcp comment 'SSH access'
# View comments
sudo ufw status verbose
Managing Rules¶
List Rules¶
# Basic list
sudo ufw status
# Verbose (shows policy)
sudo ufw status verbose
# Numbered (for deletion)
sudo ufw status numbered
Delete Rules¶
# By specification
sudo ufw delete allow 80
# By number
sudo ufw status numbered
sudo ufw delete 3
# Confirm before delete
sudo ufw delete allow ssh
# Deleting:
# allow 22/tcp
# Proceed with operation (y|n)?
Insert Rules¶
# Insert at position
sudo ufw insert 1 deny from 10.0.0.1
# Useful when you need rule to be processed first
Prepend Rules¶
Configuration Files¶
/etc/default/ufw¶
Main UFW settings:
# Enable/disable
ENABLED=yes
# Default policies
DEFAULT_INPUT_POLICY="DROP"
DEFAULT_OUTPUT_POLICY="ACCEPT"
DEFAULT_FORWARD_POLICY="DROP"
DEFAULT_APPLICATION_POLICY="SKIP"
# IPv6 support
IPV6=yes
# Manage built-in chains
MANAGE_BUILTINS=no
# IPT modules
IPT_MODULES="nf_conntrack_ftp nf_conntrack_tftp"
/etc/ufw/ufw.conf¶
Runtime configuration:
/etc/ufw/sysctl.conf¶
Kernel parameters UFW sets:
# Forwarding
net/ipv4/ip_forward=0
# Source address verification
net/ipv4/conf/all/rp_filter=1
net/ipv4/conf/default/rp_filter=1
# Don't accept redirects
net/ipv4/conf/all/accept_redirects=0
net/ipv4/conf/all/send_redirects=0
# Log martians
net/ipv4/conf/all/log_martians=1
Note
These are applied when UFW starts, potentially overriding other settings.
Editing before.rules¶
Adding NAT Rules¶
# /etc/ufw/before.rules
# Add NAT section at the BEGINNING of the file
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
# Masquerade for VM network
-A POSTROUTING -s 192.168.122.0/24 -o eth0 -j MASQUERADE
# Port forwarding
-A PREROUTING -i eth0 -p tcp --dport 8080 -j DNAT --to-destination 192.168.122.10:80
COMMIT
# Existing *filter section follows...
Adding Custom Filter Rules¶
# /etc/ufw/before.rules
# In the *filter section, before the COMMIT
# Allow all on VM bridge
-A ufw-before-forward -i virbr0 -j ACCEPT
-A ufw-before-forward -o virbr0 -j ACCEPT
# Allow specific forward
-A ufw-before-forward -s 192.168.122.0/24 -d 192.168.1.0/24 -j ACCEPT
Complete before.rules Example¶
#
# /etc/ufw/before.rules
#
# Rules that should be run before the ufw command line added rules.
# NAT table rules
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
# NAT for VM network
-A POSTROUTING -s 192.168.122.0/24 -o eth0 -j MASQUERADE
# NAT for Docker (if iptables: false)
# -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
# Port forwarding examples
# -A PREROUTING -i eth0 -p tcp --dport 2222 -j DNAT --to 192.168.122.10:22
COMMIT
# Filter table rules
*filter
:ufw-before-input - [0:0]
:ufw-before-output - [0:0]
:ufw-before-forward - [0:0]
:ufw-not-local - [0:0]
# Allow all on loopback
-A ufw-before-input -i lo -j ACCEPT
-A ufw-before-output -o lo -j ACCEPT
# Quickly process established connections
-A ufw-before-input -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-output -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-forward -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# Drop invalid
-A ufw-before-input -m conntrack --ctstate INVALID -j ufw-logging-deny
-A ufw-before-input -m conntrack --ctstate INVALID -j DROP
# Allow ICMP
-A ufw-before-input -p icmp --icmp-type destination-unreachable -j ACCEPT
-A ufw-before-input -p icmp --icmp-type time-exceeded -j ACCEPT
-A ufw-before-input -p icmp --icmp-type parameter-problem -j ACCEPT
-A ufw-before-input -p icmp --icmp-type echo-request -j ACCEPT
# Allow DHCP client
-A ufw-before-input -p udp --sport 67 --dport 68 -j ACCEPT
# VM bridge forwarding (libvirt)
-A ufw-before-forward -i virbr0 -j ACCEPT
-A ufw-before-forward -o virbr0 -j ACCEPT
# Docker bridge forwarding (if needed)
# -A ufw-before-forward -i docker0 -j ACCEPT
# -A ufw-before-forward -o docker0 -j ACCEPT
# ufw-not-local
-A ufw-before-input -j ufw-not-local
-A ufw-not-local -m addrtype --dst-type LOCAL -j RETURN
-A ufw-not-local -m addrtype --dst-type MULTICAST -j RETURN
-A ufw-not-local -m addrtype --dst-type BROADCAST -j RETURN
-A ufw-not-local -m limit --limit 3/min --limit-burst 10 -j ufw-logging-deny
-A ufw-not-local -j DROP
# Allow mDNS
-A ufw-before-input -p udp -d 224.0.0.251 --dport 5353 -j ACCEPT
# Allow UPnP
-A ufw-before-input -p udp -d 239.255.255.250 --dport 1900 -j ACCEPT
COMMIT
Applying Changes¶
# Reload after editing files
sudo ufw reload
# Or restart
sudo ufw disable && sudo ufw enable
# Verify rules loaded
sudo ufw status verbose
sudo iptables -L -n -v
Backup and Restore¶
Backup Rules¶
# Backup user rules
sudo cp /etc/ufw/user.rules /etc/ufw/user.rules.backup
sudo cp /etc/ufw/user6.rules /etc/ufw/user6.rules.backup
# Backup all config
sudo cp -r /etc/ufw /etc/ufw.backup
# Export iptables (more complete)
sudo iptables-save > ~/iptables-backup.rules
Restore Rules¶
# Restore UFW config
sudo cp -r /etc/ufw.backup/* /etc/ufw/
sudo ufw reload
# Or restore iptables directly
sudo iptables-restore < ~/iptables-backup.rules
Common Configurations¶
Basic Server¶
Web Server¶
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 'Nginx Full' # 80, 443
sudo ufw enable
Database Server (Internal Only)¶
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow from 192.168.1.0/24 to any port 5432 # PostgreSQL
sudo ufw allow from 192.168.1.0/24 to any port 3306 # MySQL
sudo ufw enable