techlogia — AI and Web Development Berlin
All courses
Free to read – no sign-up

Linux Firewall with nftables

You learn nftables — the modern successor to iptables, now the default on 75% of Linux servers. You build a production-grade firewall step by step: create tables and chains, allow SSH and HTTP/S, block everything else, and persist your rules. 6 tasks, about 75 minutes.

Duration: 75 minLevel: IntermediateExercises: 6

Build a production firewall with nftables

What is a firewall — and what is nftables?

A firewall is a filter that decides which network packets may reach a server and which are dropped. It is a server's first line of defence: without one, every open service is directly exposed to the internet.

nftables is the modern firewall framework of the Linux kernel. It replaces the older iptables and is the standard on most Linux servers today. You describe in a clear syntax what traffic is allowed — everything else is blocked.

The three building blocks of nftables

  • Table: the top-level container for your rules. Its family defines what it applies to — inet covers both IPv4 and IPv6.
  • Chain: attaches to a hook, a fixed point in the kernel's packet path. The input chain handles all incoming packets. Every chain has a policy (default behaviour): policy drop means "drop everything that no rule explicitly allows" — the safe default-deny principle.
  • Rule: a single allowance inside a chain, e.g. "permit TCP port 22 (SSH)".

Your goal in this lesson

You build a production-grade firewall step by step: an inet table with an input chain (default drop) that allows only the essentials — SSH (port 22), HTTP (80), HTTPS (443), already-established connections, and local loopback. Finally you make the rules survive a reboot. The VM starts with no active firewall rules.

Exercises

  1. 1. Create inet table

    Concept: table. The table is the top-level container in nftables — it will hold your chains and rules. The family defines which protocols it applies to: inet means IPv4 and IPv6 together, so you maintain your rules only once.

    Create a table named filter in the inet family:

    nft add table inet filter

    Check: nft list tables lists all tables — table inet filter must appear.

  2. 2. Create input chain with drop policy

    Concept: chain & policy. A chain attaches to a hook — a fixed point in the kernel's packet path. The input hook intercepts all incoming packets. The policy is the default behaviour when no rule matches: policy drop = drop everything (default-deny). That is safer than accept, because you then explicitly allow only what you need.

    In the inet filter table, create an input chain with a drop policy:

    nft 'add chain inet filter input { type filter hook input priority 0; policy drop; }'

    ⚠️ Important: Once policy drop is active, the firewall also blocks your own SSH connection — until you explicitly allow SSH in the next steps. On this practice VM that is harmless (the platform validator has its own access).

    Check: nft list chain inet filter input must show policy drop.

  3. 3. Allow established connections

    Concept: connection tracking. The kernel remembers the state of every connection. ct state established,related matches packets that belong to an already-established connection (or are directly related to one, e.g. an FTP data channel).

    Why make it the first rule? Without it, the drop policy would also discard the reply packets of your own outbound connections (e.g. the response to an apt update). This rule lets exactly those legitimate replies back in — so it belongs at the very top.

    nft add rule inet filter input ct state established,related accept

    Check: nft list chain inet filter input contains ct state established.

  4. 4. Allow SSH, HTTP, and HTTPS

    Concept: port & dport. A port is the "door" to a specific service on the server. dport (destination port) is the target port of the incoming packet. You explicitly allow the services that should be reachable from outside:

    • 22 = SSH (remote access / administration)
    • 80 = HTTP (unencrypted website, also used for the Let's Encrypt check)
    • 443 = HTTPS (encrypted website)

    Add three rules — one per port:

    nft add rule inet filter input tcp dport 22 accept
    nft add rule inet filter input tcp dport 80 accept
    nft add rule inet filter input tcp dport 443 accept

    Check: nft list chain inet filter input shows dport 22, dport 80 and dport 443, each with accept.

  5. 5. Allow loopback interface

    Concept: loopback (lo). The loopback interface lo is the server's internal network interface to itself (address 127.0.0.1). Many local services — databases, caches, mail — communicate exclusively over lo. If the drop policy also blocks loopback, these internal connections break — a common, hard-to-find bug.

    Allow all traffic that comes in over the lo interface:

    nft add rule inet filter input iifname lo accept

    iifname = input interface name, i.e. the interface the packet arrived on.

    Check: nft list chain inet filter input contains an lo rule with accept.

  6. 6. Persist the ruleset

    Problem: nftables rules live only in memory (the kernel). After a reboot they would be gone — the server would stand there with no firewall. You therefore have to make them persistent, in two steps:

    1. Export the rules to a file: /etc/nftables.conf is the standard file nftables reads on startup.
    2. Enable the service: systemctl enable nftables makes nftables start automatically at boot and load /etc/nftables.conf.
    nft list ruleset > /etc/nftables.conf
    systemctl enable nftables

    Check: /etc/nftables.conf contains table inet filter, and systemctl is-enabled nftables reports enabled.

Now practice it yourself

Reading is good – doing is better. Start this course on a real Linux VM, right in your browser. A free account is all it takes.

Start for free

Lab content under CC BY 4.0 – free to use with attribution (© TechLogia).

Linux Firewall with nftables