Skip to content
intermediate Phase 4 · Linux and Windows Security Administration

Linux Firewalls with nftables

Write default-deny rulesets that permit only sanctioned flows.

55m
0 problems
Topic Progress 0%

Linux Firewalls with nftables: Core Concepts

Linux Firewalls with nftables: Core Concepts

A Linux firewall decides which network packets are allowed to enter, leave, or pass through the system. nftables is the modern framework that replaced iptables, providing a unified syntax for IPv4, IPv6, ARP, and bridge traffic, with atomic rule updates that eliminate the race conditions of the older iptables-restore approach.

Why nftables Replaced iptables

iptables had four separate kernel modules (iptables, ip6tables, arptables, ebtables) each with its own syntax and rule storage. A rule update required flushing and reloading the entire rule set, creating a window where the firewall was in an inconsistent state.

nftables unified these into a single framework with:

  • One syntax for all protocol families
  • Atomic updates — the entire rule set is replaced in a single transaction
  • Maps and sets for efficient matching against large lists of IPs or ports
  • Better performance through bytecode compilation in the kernel

The nftables Architecture

nftables organizes rules into tables, which contain chains, which contain rules.

  • Table — A container for chains, bound to a protocol family (ip, ip6, inet, arp, bridge, netdev).
  • Chain — A sequence of rules attached to a hook in the network stack. Chains have a type (filter, route, nat) and a priority that determines evaluation order.
  • Rule — A single match-and-action statement within a chain.

The five chain hooks in the network stack are:

Hook Direction Purpose
prerouting Incoming Before routing decision (DNAT, filtering)
input Incoming Packets destined for the local system
forward Through Packets routed through the system
output Outgoing Packets generated by the local system
postrouting Outgoing After routing decision (SNAT, masquerade)

Basic Rule Syntax

# Create a table
nft add table inet filter

# Create a chain for incoming traffic
nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }

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

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

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

# Drop everything else (implicit with policy drop)

The inet family handles both IPv4 and IPv6 in a single table, which is the recommended approach for most use cases.

Sets and Maps for Efficient Matching

Instead of writing dozens of individual rules, nftables lets you define sets:

# Create a set of allowed IPs
nft add set inet filter allowed_ips { type ipv4_addr \; flags interval \; }

# Populate the set
nft add element inet filter allowed_ips { 10.0.0.0/8, 192.168.1.0/24 }

# Use the set in a rule
nft add rule inet filter input ip saddr @allowed_ips tcp dport 22 accept

With flags interval, nftables uses an interval tree for O(log n) lookups instead of linear scanning, making it practical to match against thousands of IPs.

Where It Fits

nftables operates at the network layer. It controls which packets reach the system but does not inspect application-layer content. For application-layer filtering, you need a web application firewall (WAF) or proxy. Study SSH hardening first to understand what services need to be protected, then use nftables to restrict access to those services.

Linux Firewalls with nftables: Practice

Linux Firewall with nftables: Practice

Firewall rules are unforgiving — a single mistake can lock you out of a remote server. The exercises below build up from a basic web server configuration to a more complex multi-zone setup.

Exercise 1: Basic Web Server Firewall

Configure nftables to allow only HTTP, HTTPS, and SSH, dropping everything else:

#!/usr/sbin/nft -f

flush ruleset

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

        # Allow established and related connections
        ct state established,related accept

        # Allow loopback
        iif lo accept

        # Allow ICMP (ping)
        ip protocol icmp accept
        ip6 nexthdr icmpv6 accept

        # Allow SSH
        tcp dport 22 accept

        # Allow HTTP and HTTPS
        tcp dport { 80, 443 } accept

        # Log and drop everything else
        limit rate 5/second burst 10 packets log prefix "nft-drop: " drop
    }

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

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

Apply the ruleset:

nft -f firewall.nft
nft list ruleset    # Verify

The limit rate 5/second on the log rule prevents log flooding from a port scan while still capturing evidence of the scan.

Exercise 2: Rate Limiting to Prevent Brute Force

Protect SSH from brute-force attacks by rate-limiting new connections:

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

        ct state established,related accept
        iif lo accept

        # Rate-limit SSH: max 3 new connections per minute per source IP
        tcp dport 22 ct state new limit rate 3/minute accept

        tcp dport { 80, 443 } accept
    }
}

The ct state new ensures the rate limit only applies to new connections, not to packets belonging to already-established sessions.

Exercise 3: NAT and Port Forwarding

If your server acts as a gateway for internal machines, configure source NAT (masquerading):

table ip nat {
    chain postrouting {
        type nat hook postrouting priority 100;

        # Masquerade outgoing traffic on the external interface
        oifname "eth0" masquerade
    }
}

For port forwarding (destination NAT):

table ip nat {
    chain prerouting {
        type nat hook prerouting priority 0;

        # Forward port 8080 to internal server
        tcp dport 8080 dnat to 192.168.1.50:80
    }
}

Check Your Understanding

  • Why is ct state established,related accept typically the first rule in the input chain?
  • What happens if you set policy drop but forget to allow loopback traffic?
  • How does flags interval in a set improve performance over a simple list of IPs?

Linux Firewalls with nftables: Trade-offs and Interviews

Linux Firewalls with nftables: Trade-offs and Interviews

nftables is powerful but not always the right tool. Understanding its limitations and alternatives is critical for making sound architectural decisions.

When nftables Is the Wrong Tool

  • Cloud environments: In AWS, GCP, or Azure, security groups and network ACLs operate at the hypervisor level, before traffic reaches your VM. Managing firewall rules in both places creates confusion. Use cloud-native controls for network-level filtering and nftables only for host-level granularity.
  • Container orchestration: Kubernetes Network Policies and service meshes (Istio, Linkerd) handle pod-to-pod traffic. nftables rules on the host can conflict with kube-proxy's rules.
  • Application-layer filtering: nftables matches on IP, port, and protocol. It cannot inspect HTTP headers, SQL queries, or JSON payloads. For that, you need a WAF like ModSecurity or a reverse proxy with filtering capabilities.

Performance Considerations

nftables compiles rules to bytecode that runs in the kernel, which is significantly faster than iptables' linear rule evaluation. However:

  • Large rule sets still have a cost. A ruleset with 10,000 rules will be slower than one with 100 rules, even with bytecode compilation.
  • Sets with interval flags use O(log n) lookup, but a set without flags uses O(n) linear scan. For large IP lists, always use flags interval.
  • Connection tracking (conntrack) consumes memory. On a busy server, the conntrack table can fill up, causing new connections to be dropped. Monitor with conntrack -C and adjust nf_conntrack_max if needed.

Persistence Across Reboots

nftables rules are not persistent by default. After a reboot, the ruleset is empty. To persist:

# Save current ruleset
nft list ruleset > /etc/nftables.conf

# Enable the service to load on boot
systemctl enable nftables

The nftables.service reads /etc/nftables.conf at startup. Without this step, your firewall is inactive after every reboot.

How This Comes Up in Interviews

  • "How do you prevent locking yourself out when applying firewall rules?" Use a scheduled job to reset the firewall after a timeout: nft flush ruleset && nft -f /etc/nftables.conf run via at or systemd-run with a 5-minute delay. If your rules are wrong, the reset restores access.
  • "When would you use nftables vs. cloud security groups?" Use cloud security groups for coarse-grained network segmentation (which subnets can reach the VM) and nftables for host-level granularity (which users can access which services, rate limiting, logging).
  • "How do you handle firewall rules in a containerized environment?" Let the orchestrator (Kubernetes Network Policies, Calico) handle inter-pod traffic. Use nftables only for host-level protections like rate limiting and logging.

Practice Problems

0 / 2 solved

Solution
```bash
#!/usr/sbin/nft -f

flush ruleset

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

        ct state established,related accept
        iif lo accept

        ip saddr 10.0.0.0/8 tcp dport 22 accept
        tcp dport { 80, 443 } accept

        limit rate 5/second burst 10 packets log prefix "dropped: " drop
    }
}
```

Solution
The filter chain with input hook filters packets destined for the local system — it decides what the host accepts. The nat chain with prerouting hook modifies packets before routing — it is used for DNAT (port forwarding). Use filter/input for access control and nat/prerouting for destination NAT.

Quiz

1. What is the primary advantage of nftables over iptables?

Question 1 options

2. In nftables, what does 'ct state established,related accept' accomplish?

Question 2 options

3. What does 'flags interval' in an nftables set provide?

Question 3 options

4. Why are nftables rules not persistent across reboots by default?

Question 4 options

Flashcards

Question

What are the five chain hooks in nftables?

Answer

prerouting, input, forward, output, postrouting — each corresponds to a point in the network stack's packet processing pipeline.

Question

What does 'policy drop' on a chain mean?

Answer

If no rule in the chain matches a packet, the packet is dropped. This is the secure default for input and forward chains.

Question

Why use the 'inet' table family instead of 'ip'?

Answer

The 'inet' family handles both IPv4 and IPv6 in a single table, avoiding duplicate rules for each protocol.

Question

What is the purpose of 'ct state new' in a rate-limiting rule?

Answer

It ensures the rate limit only applies to new connections, not to packets belonging to already-established sessions.

Question

How do you persist nftables rules across reboots?

Answer

Save with 'nft list ruleset > /etc/nftables.conf' and enable the nftables.service to load it at boot.

Revision Notes

Key Takeaways

  • 1. nftables replaces iptables with unified syntax and atomic rule updates.
  • 2. The inet family handles both IPv4 and IPv6 in a single table.
  • 3. policy drop is the secure default for input and forward chains.
  • 4. Sets with flags interval provide O(log n) lookup for large IP lists.
  • 5. Rules are not persistent by default — save to /etc/nftables.conf and enable the service.

Interview Tips

  • • Explain the table-chain-rule hierarchy and how hooks map to the network stack.
  • • Discuss when nftables is the wrong tool (cloud environments, container orchestration).
  • • Describe how to prevent lockout when applying firewall rules (scheduled reset).
  • • Connect nftables to defense-in-depth: it is one layer alongside SSH hardening and audit logging.

Cheat Sheet

nftables Cheat Sheet

Phase: Linux and Windows Security Administration | Level: intermediate

Architecture:

  • Table → Chain → Rule
  • Five hooks: prerouting, input, forward, output, postrouting
  • Chain types: filter, route, nat

Basic Commands:

  • nft add table inet filter — Create a table
  • nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; } — Create a chain
  • nft add rule inet filter input ct state established,related accept — Allow established
  • nft list ruleset — Show current rules
  • nft flush ruleset — Remove all rules

Persistence:

  • nft list ruleset > /etc/nftables.conf
  • systemctl enable nftables

Key Patterns:

  • ct state established,related accept — First rule in input chain
  • iif lo accept — Allow loopback
  • tcp dport { 80, 443 } accept — Multiple ports
  • limit rate 5/second burst 10 packets log prefix "drop: " drop — Rate-limited logging

Tags: linux, firewall

Continue Learning

Before You Start

  • No prerequisites listed.

Next Topics