Building a Router with RPI5

Author(s): Louis Ouellet


A compact, high-performance home/SMB router built on Raspberry Pi 5 with the Radxa Dual 2.5G Router HAT. Runs on Raspberry Pi OS with a lean Linux stack (ifupdown + iptables + dnsmasq) and optional services like Pi-hole, Unbound (recursive DNS), and a Wi-Fi AP. The project includes shell scripts and documentation to reproduce the setup end-to-end, including NVMe migration for reliability and speed.

Features

  • Three-zone routing: WAN (eth0), LAN (eth1), DMZ (eth2)
  • Clean networking: ifupdown for addresses, iptables for firewall/NAT, dnsmasq for DHCP
  • sane defaults: secure INPUT policy, LAN-only SSH, DHCP/DNS per zone, NAT out via WAN
  • NVMe boot/migration: scripted SD→NVMe clone, resize, and boot order tweak
  • Optional Pi-hole: Pi-hole owns :53; system dnsmasq does DHCP + local DNS on :5353
  • Optional Unbound: local recursive resolver on 127.0.0.1#5335 (DNSSEC, no 3rd-party upstreams)
  • Optional Wi-Fi AP: guest (routed subnet on wlan0) or bridged (LAN extender via br0)
  • Idempotent scripts: re-runnable installers that won’t clobber working configs
  • Firewall extras: examples for port-forward, DNS-redirect, and guest isolation

Network Topology

               Internet
                  │
               [eth0]  WAN  ← DHCP/PPPoE
   ┌───────────── RPi 5 ─────────────┐
   │                                 │
[eth1] LAN 192.168.10.0/24      [eth2] DMZ 192.168.20.0/24
GW: 192.168.10.1                 GW: 192.168.20.1
   │                                 │
 Switch / PCs / NAS              Servers / Public apps

Optional Wi-Fi:
- Guest AP (routed): wlan0 → 192.168.30.0/24 (isolated by default)
- Bridged AP: br0 = eth1 + wlan0 (Wi-Fi extends the LAN at L2)

Defaults & Behavior

  • Subnets: LAN 192.168.10.0/24, DMZ 192.168.20.0/24 (guest Wi-Fi 192.168.30.0/24 if enabled)
  • Gateway IPs: LAN 192.168.10.1, DMZ 192.168.20.1, Wi-Fi 192.168.30.1
  • DHCP pools: .100.200 per subnet (configurable in scripts)
  • Firewall:
    • INPUT: DROP by default; allow loopback, established/related, DHCP/DNS from LAN/DMZ, SSH from LAN only
    • FORWARD: allow LAN/DMZ→WAN; block unsolicited WAN→LAN/DMZ; LAN↔DMZ blocked unless explicitly allowed
    • NAT: MASQUERADE out via WAN
  • Pi-Hole mode (optional): Pi-hole/FTL on :53; system dnsmasq on :5353 serves local zones; Pi-hole forwards lan/dmz to 127.0.0.1#5353
  • Unbound (optional): Pi-hole upstream set to 127.0.0.1#5335 for local recursion (DNSSEC in Unbound)

Quick Start

Requires Raspberry Pi OS (Bookworm), RPi5 with Radxa Dual 2.5G HAT, and basic console access.

# 1) Get the installer
curl -fsSL https://raw.githubusercontent.com/LaswitchTech/router-pi5/stable/install.sh -o install.sh
chmod +x install.sh
 
# 2) Run base router setup (ifupdown + iptables + dnsmasq)
sudo ./install.sh
 
# 3) (Optional) Add services later
#   Pi-hole DNS front-end
sudo ./add-pihole.sh
#   Unbound recursive resolver
sudo ./add-unbound.sh
#   Guest Wi-Fi AP (routed)
sudo ./add-ap-wifi-guest.sh
#   Bridged Wi-Fi AP (LAN extender)
sudo ./add-ap-wifi-bridge.sh

Heads-up: if you already installed Pi-hole, it binds port 53. The system dnsmasq used for DHCP must be moved to port 5353 (the scripts handle this). To diagnose conflicts: sudo ss -lunp '( sport = :53 or sport = :5353 )'

Documentation

Review the full documentation including:

  • Installation (router base, NVMe migration)
  • Pi-hole integration (dnsmasq → 5353, local zones, optional DNS redirect)
  • Unbound (secure recursion, DNSSEC)
  • Wi-Fi AP (guest routed vs bridged)
  • Port forwarding & hairpin NAT examples
  • Troubleshooting (port 53 conflicts, DHCP scope, PCIe enable on Pi 5)

Hardware, Parts & Costs

Brand Part Vendor Qty Price
Raspberry Pi 5 (4–8 GB) Amazon 1 143.00 $CAD
Raspberry Pi 5 Active Cooler Amazon 1 17.31 $CAD
Radxa Dual 2.5G Router HAT AliExpress 1 60.68 $CAD
Radxa Power DC12 60W AliExpress 1 17.89 $CAD
Total 238.88 $CAD

Roadmap

  • Merge add-on scripts behind install.sh flags (e.g., –with-pihole, –with-unbound, –with-ap-guest|bridge)
  • Optional PHP admin for templating configs & safe reloads (diff + rollback)
  • SQM/CAKE for bufferbloat control
  • WireGuard site-to-site & remote-access presets
  • VLAN templates and multiple SSID support (hostapd multi-BSS)

Troubleshooting Snippets

# Who's using port 53 / 5353?
sudo ss -lntup '( sport = :53 or sport = :5353 )'
sudo ss -lunp  '( sport = :53 or sport = :5353 )'
 
# Pi-hole DNS reload + logs
sudo pihole reload dns
journalctl -u pihole-FTL -n 50 --no-pager
 
# dnsmasq status & lease file
systemctl status dnsmasq
cat /var/lib/misc/dnsmasq.leases

License & Credits

Code and docs are in the repo; see LICENSE file for details. Thanks to the Raspberry Pi, Radxa, and open-source communities.


Tags

Discussion

Enter your comment. Wiki syntax is allowed:
Y A P H T