Linux··4 min

Firewall — iptables and ufw

The Linux firewall is built into the kernel. iptables has been the tool to configure it for decades. ufw makes the common cases much simpler. This post covers how it all fits together.

The Linux firewall is built into the kernel. It is called netfilter, and it filters every packet that enters, leaves, or passes through your machine. iptables is the traditional userspace tool for configuring it. ufw (Uncomplicated Firewall) is a frontend that makes it significantly less painful to work with.

How iptables works

iptables organises rules into tables, and tables contain chains. The most important table is filter, which has three built-in chains:

  • INPUT — packets destined for the local system
  • OUTPUT — packets originating from the local system
  • FORWARD — packets passing through (for routers)

Each chain contains an ordered list of rules. When a packet arrives, iptables checks it against each rule in order. The first matching rule wins. If no rule matches, the chain's default policy applies (usually ACCEPT or DROP).

Viewing current rules

sudo iptables -L -v -n
  • -L — list rules
  • -v — verbose (show packet and byte counts)
  • -n — numeric output (do not resolve hostnames or service names)

Basic iptables rules

Allow incoming SSH:

sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
  • -A INPUT — append to the INPUT chain
  • -p tcp — match TCP protocol
  • --dport 22 — match destination port 22
  • -j ACCEPT — jump to ACCEPT (allow the packet)

Allow established connections (important — without this, return traffic gets blocked):

sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

Allow loopback traffic:

sudo iptables -A INPUT -i lo -j ACCEPT

Drop everything else:

sudo iptables -P INPUT DROP

-P sets the default policy. This is the last step — set it to DROP only after you have allowed the traffic you actually need.

Saving iptables rules

iptables rules do not persist across reboots by default.

On Debian/Ubuntu:

sudo apt install iptables-persistent
sudo netfilter-persistent save

Rules are saved to /etc/iptables/rules.v4 and loaded on boot.

ufw

iptables is powerful but verbose. ufw provides a simpler interface for the most common use cases.

Enabling ufw

sudo ufw enable

Check status:

sudo ufw status verbose

Basic ufw rules

Allow SSH:

sudo ufw allow ssh

Or by port number:

sudo ufw allow 22/tcp

Allow HTTP and HTTPS:

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

Allow a port range:

sudo ufw allow 8000:8100/tcp

Allow from a specific IP:

sudo ufw allow from 192.168.1.50

Allow from a specific IP to a specific port:

sudo ufw allow from 192.168.1.50 to any port 5432

Deny a port:

sudo ufw deny 3306

Delete a rule:

sudo ufw delete allow 80/tcp

ufw default policies

sudo ufw default deny incoming
sudo ufw default allow outgoing

This is the standard server setup — deny all incoming traffic by default and only allow what you explicitly open. Set the defaults before enabling ufw.

ufw application profiles

Some packages install ufw profiles that you can use by name:

sudo ufw app list
sudo ufw allow "Nginx Full"
sudo ufw allow "OpenSSH"

nftables

nftables is the modern replacement for iptables. It uses a cleaner syntax, performs better, and is now the default on newer distributions.

Check if nftables is active:

sudo nft list ruleset

A basic nftables configuration that allows SSH, HTTP, HTTPS and drops everything else:

table inet filter {
    chain input {
        type filter hook input priority 0; policy drop;

        iif lo accept
        ct state established,related accept
        tcp dport { 22, 80, 443 } accept
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
    }

    chain output {
        type filter hook output priority 0; policy accept;
    }
}

Save this to /etc/nftables.conf and enable the service:

sudo systemctl enable --now nftables

A practical server setup

The standard hardened server firewall in order:

# Set defaults
sudo ufw default deny incoming
sudo ufw default allow outgoing
 
# Allow SSH (do this before enabling or you lock yourself out)
sudo ufw allow ssh
 
# Allow web traffic if running a web server
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
 
# Enable
sudo ufw enable
 
# Verify
sudo ufw status verbose

The firewall is the boundary between your system and everything else. For any internet-facing server, getting it right is not optional. The ufw workflow above covers most cases. Learn iptables when you need finer control or are working with systems where ufw is not available.

Next up: environment variables and the shell — PATH, .bashrc, and how shell startup actually works.

0 views