Using a Raspberry Pi as router hardware is a highly capable project, provided you bypass the bottlenecks that trap most beginners. The Raspberry Pi 5 can push over 900 Mbps of NAT throughput on its CPU, but the onboard Gigabit Ethernet and USB 3.0 bus share bandwidth constraints. To build a true dual-interface gateway without choking your uplink, you need a specific hardware topology and modern nftables routing, rather than deprecated iptables scripts.
This guide targets the Raspberry Pi 5 (8GB variant) running Raspberry Pi OS (64-bit, Bookworm or newer). We will configure the onboard Gigabit port for your local wired LAN, a USB-C 2.5GbE adapter for your WAN uplink, and the onboard Wi-Fi 5 radio as a local Access Point (AP).
Hardware BOM & Interface Mapping
Before writing a single line of code, you must map your physical ports to logical interfaces. Using a Realtek RTL8156B-based USB adapter is mandatory here; avoid the older RTL8153 chipset, which is notorious for thermal throttling and silent packet drops under sustained router loads.
| Component | Exact Model / Variant | Logical Interface | Network Role | Est. Cost (2026) |
|---|---|---|---|---|
| Compute Core | Raspberry Pi 5 (8GB RAM) | N/A | Routing & NAT Engine | $80 |
| WAN NIC | USB-C to 2.5GbE (RTL8156B Chipset) | eth1 |
Internet Uplink (WAN) | $25 |
| LAN NIC | Onboard Gigabit Ethernet | eth0 |
Wired Local Network | $0 (Included) |
| WLAN AP | Onboard Dual-Band 802.11ac (Wi-Fi 5) | wlan0 |
Wireless Access Point | $0 (Included) |
| Storage | 64GB NVMe via PCIe HAT (e.g., Argon) | N/A | OS, Logs & DHCP Leases | $35 |
Network Topology & Routing Logic
The topology relies on Network Address Translation (NAT) to bridge your private LAN/WLAN to the public WAN. Traffic entering eth0 (wired) or wlan0 (wireless) is routed through the Pi's kernel, masqueraded via nftables, and pushed out to eth1 (WAN).
- WAN (
eth1): Configured via DHCP client to pull an IP from your ISP's modem. - LAN (
eth0): Statically assigned192.168.10.1/24. Runsdnsmasqfor DHCP server duties. - WLAN (
wlan0): Statically assigned192.168.20.1/24(isolated subnet for wireless clients). Runshostapdfor AP management anddnsmasqfor wireless DHCP.
The Configuration Script
Modern Debian-based distributions (including Raspberry Pi OS Bookworm) have moved to nftables. The script below flushes legacy rules, enables kernel IP forwarding, and sets up the NAT masquerade. It includes strict interface verification to prevent locking yourself out of the board if a USB cable is bumped.
#!/bin/bash
# Target: Raspberry Pi 5 (8GB) running Raspberry Pi OS (64-bit, Bookworm+)
# Purpose: Configure nftables NAT and IP forwarding for dual-interface routing
set -euo pipefail
# Define logical interfaces based on hardware mapping
WAN_IF="eth1" # USB 2.5GbE Adapter (RTL8156B)
LAN_IF="eth0" # Onboard Gigabit Ethernet
WLAN_IF="wlan0" # Onboard Wi-Fi 5
# 1. Verify interfaces exist before modifying kernel state
for iface in $WAN_IF $LAN_IF $WLAN_IF; do
if ! ip link show "$iface" > /dev/null 2>&1; then
echo "FATAL: Interface $iface not found. Check physical connections and dmesg."
exit 1
fi
done
# 2. Enable IPv4 forwarding in the kernel
sysctl -w net.ipv4.ip_forward=1
# 3. Flush existing nftables to ensure a clean state
nft flush ruleset
# 4. Build the NAT and Filter tables
nft add table ip filter
nft add chain ip filter forward { type filter hook forward priority 0 \; policy drop \; }
nft add rule ip filter forward iifname "$LAN_IF" oifname "$WAN_IF" accept
nft add rule ip filter forward iifname "$WLAN_IF" oifname "$WAN_IF" accept
nft add rule ip filter forward iifname "$WAN_IF" oifname "$LAN_IF" ct state established,related accept
nft add rule ip filter forward iifname "$WAN_IF" oifname "$WLAN_IF" ct state established,related accept
nft add table ip nat
nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }
nft add rule ip nat postrouting oifname "$WAN_IF" masquerade
echo "Routing, NAT, and firewall rules applied successfully."
Save this as /usr/local/bin/pi-router-nat.sh, make it executable (chmod +x), and bind it to a systemd service that triggers after network-online.target to ensure the USB adapter has fully enumerated before the script runs.
Debugging: Driver Faults & Interface Locks
When configuring the Wi-Fi AP using hostapd, you will inevitably hit driver contention issues. The Raspberry Pi's Wi-Fi chip is highly sensitive to multiple services trying to claim the radio simultaneously.
nl80211: Could not configure driver modewlan0: Failed to initialize driver interface
If you see this in your journalctl -u hostapd logs, do not reboot immediately. Here are the first three things to check, ranked by probability:
- NetworkManager Interference (90% of cases): NetworkManager or
wpa_supplicantis holding a lock onwlan0.
Fix: Runsudo nmcli radio wifi offandsudo systemctl stop wpa_supplicant. To make it permanent, mask the service:sudo systemctl mask wpa_supplicant. - Missing Regulatory Domain (8% of cases): The Wi-Fi chip refuses to transmit or enter AP mode if the country code is unset, as it doesn't know which frequencies are legal.
Fix: Runsudo raspi-config, navigate to Localisation Options > WLAN Country, and set your region. Alternatively, addcountry_code=US(or your ISO code) directly into yourhostapd.conf. - RFKill Soft Block (2% of cases): The kernel's radio frequency kill switch is engaged.
Fix: Runsudo rfkill list. Ifwlan0shows "Soft blocked: yes", clear it withsudo rfkill unblock wlan.
For deeper hostapd configuration parameters and hardware-specific driver flags, always refer to the official hostapd documentation rather than outdated forum posts.
Extending or Simplifying the Build
Once your base router is passing traffic, you have two distinct paths forward depending on your project goals.
How to Extend the Build (Advanced)
If you want to maximize performance and replicate commercial router features, implement SQM (Smart Queue Management). Bufferbloat will destroy your latency under heavy load, even with a 2.5Gbps WAN link. Install the sqm-scripts package and configure the cake qdisc on your eth1 (WAN) interface. Set the bandwidth limit to 90% of your actual ISP provisioned speed. This single addition will drop your loaded ping latency from 200ms+ down to sub-15ms.
You can also extend the topology by adding 802.1Q VLAN tagging. By utilizing a managed switch on the eth0 port, you can route eth0.10 (IoT devices) and eth0.20 (Trusted LAN) through the Pi, applying strict nftables drop rules between the subnets while allowing both to reach the WAN.
How to Simplify the Build (Pragmatic)
If maintaining raw Debian config files, dnsmasq leases, and systemd dependencies feels like overkill, abandon bare-metal Raspberry Pi OS. Flash OpenWrt onto your NVMe drive. OpenWrt abstracts the nftables, hostapd, and DHCP stacks into the LuCI web GUI. You retain the exact same hardware BOM, but you gain a unified dashboard for managing firewall zones, QoS, and package installations without touching the command line.
Whether you build it from scratch to understand the Linux networking stack or flash OpenWrt for daily reliability, the Pi 5's PCIe and USB 3.0 bandwidth finally makes it a legitimate contender in the homelab router space.






