Firewall Deep Dive#

Prerequisite — Packet Filtering Refresher: A firewall examines network packets and decides whether to accept, drop (silently ignore), or reject (refuse with a response) each one. Linux’s built-in firewall lives in the kernel (netfilter). Tools like ufw, iptables, and nftables are user-space interfaces for configuring it. This lesson builds on the firewall introduction in Module 09.

Concepts#

ufw — Uncomplicated Firewall#

ufw is the default firewall frontend on Ubuntu (also available on Debian). It provides a simple command-line interface over iptables/nftables.

Enable and Status#

sudo ufw status
sudo ufw status verbose
sudo ufw status numbered        # show rule numbers

sudo ufw enable                 # activate firewall
sudo ufw disable                # deactivate firewall
sudo ufw reset                  # remove all rules, disable

Default Policies#

# Deny all incoming, allow all outgoing (recommended default)
sudo ufw default deny incoming
sudo ufw default allow outgoing

Allow and Deny Rules#

# Allow by port
sudo ufw allow 22               # SSH
sudo ufw allow 80               # HTTP
sudo ufw allow 443              # HTTPS

# Allow by service name
sudo ufw allow ssh
sudo ufw allow http

# Allow specific protocol
sudo ufw allow 53/tcp           # DNS over TCP
sudo ufw allow 53/udp           # DNS over UDP

# Allow port range
sudo ufw allow 8000:8080/tcp

# Allow from specific IP
sudo ufw allow from 192.168.1.100
sudo ufw allow from 192.168.1.100 to any port 22

# Allow from a subnet
sudo ufw allow from 192.168.1.0/24 to any port 22

# Deny a specific IP
sudo ufw deny from 10.0.0.5

# Deny a specific port
sudo ufw deny 3306              # block MySQL from outside

Deleting Rules#

# Delete by rule
sudo ufw delete allow 80

# Delete by number (safer — check numbers first)
sudo ufw status numbered
sudo ufw delete 3

Logging#

# Enable logging
sudo ufw logging on
sudo ufw logging medium          # low, medium, high, full

# View firewall logs
grep -i ufw /var/log/syslog | tail -20
# or
journalctl | grep -i ufw | tail -20

Application Profiles#

Some packages install ufw application profiles:

# List available profiles
sudo ufw app list

# View profile details
sudo ufw app info "OpenSSH"
sudo ufw app info "Nginx Full"

# Allow by profile
sudo ufw allow "OpenSSH"

Rate Limiting#

Protect against brute-force attacks:

# Rate-limit SSH (deny connections from an IP that attempts
# more than 6 connections in 30 seconds)
sudo ufw limit ssh
sudo ufw limit 22/tcp

nftables — Modern Packet Filtering#

nftables is the successor to iptables. It is the default backend on Debian 11+ and Ubuntu 22+. While ufw uses iptables/nftables behind the scenes, understanding nftables gives you more control.

nftables vs iptables#

iptables nftables
Status Legacy (still works) Current standard
Syntax Separate commands per table Unified syntax
Tables Predefined (filter, nat, mangle) User-defined
Performance Good Better (atomic rule updates)

nftables Structure#

nftables
└── Table (family: inet, ip, ip6)
    └── Chain (type: filter, nat, route)
        └── Rule (match + action)

Basic nftables Commands#

# List current ruleset
sudo nft list ruleset

# List tables
sudo nft list tables

# Flush all rules
sudo nft flush ruleset

Example nftables Configuration#

# Create a simple firewall
sudo nft flush ruleset

sudo nft add table inet filter

# Input chain — deny by default
sudo nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }

# Allow loopback
sudo nft add rule inet filter input iif lo accept

# Allow established connections
sudo nft add rule inet filter input ct state established,related accept

# Allow SSH
sudo nft add rule inet filter input tcp dport 22 accept

# Allow HTTP and HTTPS
sudo nft add rule inet filter input tcp dport { 80, 443 } accept

# Allow ICMP (ping)
sudo nft add rule inet filter input icmp type echo-request accept

# Output chain — allow all
sudo nft add chain inet filter output { type filter hook output priority 0 \; policy accept \; }

# View the result
sudo nft list ruleset

Saving nftables Rules#

# Save current rules to file
sudo nft list ruleset > /etc/nftables.conf

# Load rules from file
sudo nft -f /etc/nftables.conf

# Enable at boot
sudo systemctl enable nftables

Ubuntu: Most users should stick with ufw — it handles everything a desktop or simple server needs. Use nftables directly for complex rulesets. Debian: ufw is available (sudo apt install ufw) but not installed by default. nftables is the standard approach.

iptables Overview (Legacy)#

Many guides still reference iptables. The concepts are the same:

# List rules
sudo iptables -L -n -v

# Allow SSH
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# Drop all other incoming
sudo iptables -P INPUT DROP

# Save rules
sudo iptables-save > /etc/iptables.rules

# On modern systems, iptables is often a compatibility wrapper around nftables:
sudo iptables --version
# iptables v1.8.9 (nf_tables)  ← using nftables backend

If you see (nf_tables) in the version output, iptables commands are translated to nftables rules automatically.


Lab#

Exercise 1: ufw Basics#

# Check status
sudo ufw status verbose

# Set up a basic firewall
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw enable

# View rules
sudo ufw status numbered

# Test rate limiting
sudo ufw limit ssh

# View status
sudo ufw status verbose

Exercise 2: ufw Rule Management#

# Add a rule
sudo ufw allow from 192.168.1.0/24 to any port 8080

# View numbered rules
sudo ufw status numbered

# Delete the rule you just added
sudo ufw delete allow from 192.168.1.0/24 to any port 8080

# Verify
sudo ufw status numbered

Exercise 3: Explore nftables#

# View current ruleset (may show ufw's rules translated to nftables)
sudo nft list ruleset 2>/dev/null | head -30

# List tables
sudo nft list tables 2>/dev/null

Exercise 4: View Firewall Logs#

# Enable ufw logging
sudo ufw logging on

# Check logs
grep -i ufw /var/log/syslog 2>/dev/null | tail -10
journalctl | grep -i ufw 2>/dev/null | tail -10

Review#

1. What is the recommended default policy for a firewall?

Deny all incoming traffic, allow all outgoing traffic. Then explicitly allow the services you need (SSH, HTTP, etc.). This follows the principle of least privilege.

2. How do you allow SSH through ufw?

sudo ufw allow ssh or sudo ufw allow 22/tcp. To restrict to a specific source: sudo ufw allow from 192.168.1.0/24 to any port 22.

3. What does `sudo ufw limit ssh` do?

Enables rate limiting on the SSH port. It denies connections from any IP that attempts more than 6 connections within 30 seconds, protecting against brute-force attacks.

4. What is nftables?

The modern replacement for iptables. It provides a unified syntax for packet filtering, NAT, and routing rules. On recent Ubuntu and Debian systems, even iptables commands use nftables as the backend.

5. Should you use ufw or nftables?

For most desktop and simple server use cases, ufw is sufficient and easier. Use nftables directly when you need complex rulesets, custom chains, or fine-grained control that ufw doesn’t expose.


Previous: Performance and Troubleshooting | Next: AppArmor