Set up nftables IPv6 NAT and dual-stack networking with firewall rules and traffic forwarding

Advanced 45 min Apr 08, 2026 1,955 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Configure nftables with IPv6 NAT masquerading, dual-stack IPv4/IPv6 forwarding, and comprehensive firewall rules for secure network routing and traffic management on modern Linux systems.

Prerequisites

  • Root access to Linux server
  • Basic understanding of network concepts
  • Two network interfaces (physical or virtual)
  • IPv6-enabled network environment

What this solves

IPv6 adoption requires proper network address translation and dual-stack configuration to ensure seamless connectivity between IPv4 and IPv6 networks. This tutorial configures nftables with IPv6 NAT masquerading, traffic forwarding between network interfaces, and comprehensive firewall rules for secure dual-stack networking.

Step-by-step configuration

Install nftables and enable IPv6 kernel modules

Install nftables package and verify IPv6 support is enabled in the kernel for dual-stack networking.

sudo apt update
sudo apt install -y nftables
sudo systemctl enable --now nftables
sudo dnf update
sudo dnf install -y nftables
sudo systemctl enable --now nftables
sudo modprobe ip6_tables
sudo modprobe ip6table_nat
echo 'ip6_tables' | sudo tee -a /etc/modules
echo 'ip6table_nat' | sudo tee -a /etc/modules

Enable IPv4 and IPv6 forwarding

Configure kernel parameters to enable packet forwarding between network interfaces for dual-stack routing.

net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.default.forwarding = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv6.conf.all.accept_ra = 0
net.ipv6.conf.default.accept_ra = 0
sudo sysctl -p /etc/sysctl.d/99-ip-forwarding.conf
sudo sysctl net.ipv4.ip_forward
sudo sysctl net.ipv6.conf.all.forwarding

Create nftables configuration with dual-stack tables

Configure separate tables for IPv4 and IPv6 traffic processing with input, forward, and output chains.

#!/usr/sbin/nft -f

# Clear all existing rules
flush ruleset

# IPv4 table configuration
table ip filter {
    chain input {
        type filter hook input priority filter; policy drop;
        
        # Allow loopback traffic
        iif "lo" accept
        
        # Allow established and related connections
        ct state established,related accept
        
        # Allow ICMP for network diagnostics
        ip protocol icmp accept
        
        # Allow SSH access (adjust port if needed)
        tcp dport 22 accept
        
        # Allow HTTP/HTTPS
        tcp dport { 80, 443 } accept
        
        # Log dropped packets
        log prefix "nftables input drop: " drop
    }
    
    chain forward {
        type filter hook forward priority filter; policy drop;
        
        # Allow established and related connections
        ct state established,related accept
        
        # Allow forwarding from internal to external
        iifname "eth1" oifname "eth0" accept
        
        # Allow forwarding from external to internal (established)
        iifname "eth0" oifname "eth1" ct state established,related accept
        
        # Log dropped forwards
        log prefix "nftables forward drop: " drop
    }
    
    chain output {
        type filter hook output priority filter; policy accept;
    }
}

# IPv4 NAT table
table ip nat {
    chain prerouting {
        type nat hook prerouting priority dstnat; policy accept;
        
        # Port forwarding example (HTTP to internal server)
        iifname "eth0" tcp dport 8080 dnat to 192.168.1.100:80
    }
    
    chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;
        
        # Masquerade outgoing traffic
        oifname "eth0" masquerade
    }
}

# IPv6 table configuration
table ip6 filter {
    chain input {
        type filter hook input priority filter; policy drop;
        
        # Allow loopback traffic
        iif "lo" accept
        
        # Allow established and related connections
        ct state established,related accept
        
        # Allow ICMPv6 for neighbor discovery and diagnostics
        ip6 nexthdr ipv6-icmp accept
        
        # Allow SSH access
        tcp dport 22 accept
        
        # Allow HTTP/HTTPS
        tcp dport { 80, 443 } accept
        
        # Allow DHCPv6
        udp dport 546 accept
        
        # Log dropped packets
        log prefix "nftables ipv6 input drop: " drop
    }
    
    chain forward {
        type filter hook forward priority filter; policy drop;
        
        # Allow established and related connections
        ct state established,related accept
        
        # Allow forwarding from internal to external
        iifname "eth1" oifname "eth0" accept
        
        # Allow forwarding from external to internal (established)
        iifname "eth0" oifname "eth1" ct state established,related accept
        
        # Log dropped forwards
        log prefix "nftables ipv6 forward drop: " drop
    }
    
    chain output {
        type filter hook output priority filter; policy accept;
    }
}

# IPv6 NAT table (requires kernel 3.7+)
table ip6 nat {
    chain prerouting {
        type nat hook prerouting priority dstnat; policy accept;
        
        # IPv6 port forwarding example
        iifname "eth0" tcp dport 8080 dnat to [2001:db8::100]:80
    }
    
    chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;
        
        # IPv6 masquerading for outgoing traffic
        oifname "eth0" masquerade
    }
}

Configure network interfaces for dual-stack

Set up network interfaces with both IPv4 and IPv6 addresses using Netplan configuration.

network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      dhcp4: true
      dhcp6: true
      accept-ra: true
      link-local: [ipv4, ipv6]
    eth1:
      addresses:
        - 192.168.1.1/24
        - 2001:db8:1::1/64
      dhcp4: false
      dhcp6: false
      accept-ra: false
sudo netplan apply
sudo networkctl status

Apply nftables configuration and enable service

Load the nftables configuration and verify rules are applied correctly for both IPv4 and IPv6 tables.

sudo nft -f /etc/nftables.conf
sudo systemctl restart nftables
sudo systemctl status nftables

Configure IPv6 router advertisements (optional)

Set up router advertisements for IPv6 prefix delegation on the internal network interface.

sudo apt install -y radvd
sudo dnf install -y radvd
interface eth1 {
    AdvSendAdvert on;
    MinRtrAdvInterval 3;
    MaxRtrAdvInterval 10;
    
    prefix 2001:db8:1::/64 {
        AdvOnLink on;
        AdvAutonomous on;
        AdvRouterAddr on;
    };
    
    RDNSS 2001:4860:4860::8888 2001:4860:4860::8844 {
        AdvRDNSSLifetime 300;
    };
};
sudo systemctl enable --now radvd

Add advanced security rules

Implement additional security measures including rate limiting and connection tracking limits.

sudo nft add rule ip filter input tcp dport 22 ct state new limit rate 5/minute accept
sudo nft add rule ip6 filter input tcp dport 22 ct state new limit rate 5/minute accept
sudo nft add rule ip filter input ct state invalid drop
sudo nft add rule ip6 filter input ct state invalid drop

Create nftables management script

Create a script for easy management of nftables rules and dual-stack configuration.

#!/bin/bash

# nftables dual-stack management script

case "$1" in
    status)
        echo "=== IPv4 Tables ==="
        nft list table ip filter
        nft list table ip nat
        echo "=== IPv6 Tables ==="
        nft list table ip6 filter
        nft list table ip6 nat
        ;;
    reload)
        echo "Reloading nftables configuration..."
        nft -f /etc/nftables.conf
        systemctl reload nftables
        echo "Configuration reloaded"
        ;;
    connections)
        echo "=== Active connections ==="
        nft list table ip nat
        nft list table ip6 nat
        ;;
    *)
        echo "Usage: $0 {status|reload|connections}"
        exit 1
        ;;
esac
sudo chmod 755 /usr/local/bin/nftables-manager.sh

Verify your setup

# Check nftables service status
sudo systemctl status nftables

# Verify IPv4 and IPv6 forwarding is enabled
sudo sysctl net.ipv4.ip_forward
sudo sysctl net.ipv6.conf.all.forwarding

# List all nftables rules
sudo nft list ruleset

# Test IPv4 connectivity
ping -c 3 8.8.8.8

# Test IPv6 connectivity
ping6 -c 3 2001:4860:4860::8888

# Check network interfaces
ip addr show
ip -6 addr show

# Verify NAT table entries
sudo /usr/local/bin/nftables-manager.sh status
Note: If IPv6 connectivity fails, verify that your ISP provides IPv6 support and that upstream routers are configured for IPv6 routing.

Common issues

SymptomCauseFix
IPv6 NAT rules not workingKernel doesn't support IPv6 NATCheck uname -r, upgrade to kernel 3.7+
No IPv6 connectivityForwarding disabled or missing modulesVerify net.ipv6.conf.all.forwarding=1 and load ip6_tables
Connection refused on forwarded portsIncorrect NAT rules or firewall blockingCheck DNAT rules and verify destination service is running
nftables service fails to startSyntax error in configurationRun nft -c -f /etc/nftables.conf to check syntax
Internal clients can't reach internetMissing masquerade rulesVerify postrouting masquerade rules for both IPv4 and IPv6
Router advertisements not workingradvd misconfigurationCheck journalctl -u radvd and verify interface names
Warning: Never use blanket allow rules like accept without proper filtering. Always implement specific rules based on required services and apply the principle of least privilege.

Next steps

Automated install script

Run this to automate the entire setup

¿Prefiere no gestionarlo usted mismo?

Gestionamos la infraestructura de empresas que dependen del tiempo de actividad. Totalmente gestionada, con un contacto fijo que conoce su entorno.

Tiene un contacto fijo que conoce su entorno

Róterdam 04:55 · accesible por mensaje, sin formulario de tickets