Protego field desk
System Hardening · Hardening

L10. Firewall Fundamentals: UFW and iptables

Course outlineLesson 10 of 20

Linux has a powerful built-in firewall that most beginners never configure. Learn how iptables chains filter network traffic, how UFW simplifies rule management, and how to implement a default-deny policy that blocks everything except what you explicitly allow.

What Does a Firewall Do at the OS Level?

A firewall inspects network packets as they enter, leave, or pass through your system and decides whether to allow, drop, or reject each one. On Linux, the kernel's netfilter framework handles this filtering at the network stack level, which means it processes packets before they ever reach an application. iptables is the traditional rule interface; nftables is its modern replacement. The iptables-nft compatibility tools translate iptables commands to nftables. UFW simplifies host rules on Ubuntu; firewalld uses nftables by default on modern RHEL. Use one firewall manager rather than mixing independently managed rule sets.

firewalld Zones

firewalld assigns interfaces or source networks to zones such as public, internal and trusted. A zone defines allowed services and ports; trusted allows all traffic. Runtime changes disappear on reload unless saved permanently.

sudo firewall-cmd --get-active-zones
sudo firewall-cmd --zone=public --add-service=ssh --permanent
sudo firewall-cmd --reload
sudo firewall-cmd --zone=public --list-all

iptables: The Foundation

Understanding Chains

iptables organizes rules into chains. Each chain handles traffic at a different point:

ChainWhen It Applies
INPUTPackets destined for this machine
OUTPUTPackets originating from this machine
FORWARDPackets passing through this machine (routing)
When a packet arrives, the kernel walks through the matching chain from top to bottom. The first matching terminating verdict (such as ACCEPT or DROP) wins; non-terminating targets such as LOG continue evaluation. If no rule matches, the chain's default policy applies.

Basic iptables Commands

# View current rules with line numbers
sudo iptables -L -n --line-numbers

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

# Allow established and related connections (critical for responses) sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Drop all other incoming traffic sudo iptables -A INPUT -j DROP

Rule Order Matters

Rules are evaluated top to bottom. If you place a DROP rule before an ACCEPT rule, the ACCEPT rule never fires. This is the most common mistake when writing iptables rules manually.

# Delete a specific rule by line number
sudo iptables -D INPUT 3

# Insert a rule at a specific position sudo iptables -I INPUT 1 -p tcp --dport 443 -j ACCEPT

Making Rules Persistent

iptables rules exist only in memory by default. They vanish after a reboot. To persist them:

# Debian/Ubuntu
sudo apt install iptables-persistent
sudo netfilter-persistent save

# Modern RHEL: use firewalld permanent rules instead of the legacy iptables service

UFW: The Friendly Frontend

UFW wraps iptables with a simpler command syntax. It is installed by default on Ubuntu and available on most distributions.

Enabling UFW

# Set default policies first
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Allow SSH before enabling (or you will lock yourself out) sudo ufw allow 22/tcp

# Enable the firewall sudo ufw enable

Common UFW Commands

# Allow HTTPS
sudo ufw allow 443/tcp

# Allow a specific IP to reach port 3306 (MySQL) sudo ufw allow from 10.0.1.50 to any port 3306

# Deny traffic from a specific subnet sudo ufw deny from 192.168.100.0/24

# View all rules with numbering sudo ufw status numbered

# Delete a rule by number sudo ufw delete 3

# Check the firewall status sudo ufw status verbose

Default Deny: The Most Important Policy

A default-deny policy means the firewall drops all incoming traffic unless a rule explicitly allows it. This is the single most impactful firewall decision you can make.

Without default deny, every new service you install automatically becomes reachable from the network. With default deny, you must consciously open each port. This aligns with the principle of least privilege applied to network access.

# iptables default deny
sudo iptables -P INPUT DROP

# UFW default deny sudo ufw default deny incoming

When to Use iptables vs UFW

ScenarioRecommended Tool
Simple server with a few open portsUFW
Complex NAT or port forwarding rulesiptables
Automated infrastructure (Ansible, Terraform)iptables or nftables
Quick setup on an Ubuntu workstationUFW
For most single-server setups, UFW is sufficient and much harder to misconfigure. As your infrastructure grows, learning raw iptables (or its successor, nftables) becomes necessary.

Verifying Your Firewall

After configuring rules, always verify from outside the machine:

# From another machine, scan common ports
nmap -sT target-server

# Check if a specific port is reachable nc -zv target-server 22

A firewall you never test is a firewall you cannot trust.

References

Exam Focus Points
  • ✓iptables uses three main chains: INPUT (incoming), OUTPUT (outgoing), and FORWARD (routed traffic)
  • ✓Rules are evaluated top to bottom in a chain: the first match wins, so rule order matters
  • ✓Default-deny policy drops all traffic not explicitly allowed, enforcing least-privilege at the network level
  • ✓UFW is a user-friendly frontend to iptables: both configure the same kernel netfilter framework
  • ✓iptables rules are lost on reboot unless saved with iptables-persistent or equivalent
Knowledge Check

1. What happens to a packet in iptables if no rule in the INPUT chain matches it?

2. Before enabling UFW with "sudo ufw enable", what is the most critical rule to add first?

3. What is the primary advantage of a default-deny firewall policy over default-allow?