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

Advanced 45 min Apr 08, 2026
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

#nftables #IPv6 NAT #dual-stack #firewall #network forwarding

Need help?

Don't want to manage this yourself?

We handle infrastructure for businesses that depend on uptime. From initial setup to ongoing operations.

Talk to an engineer