An IPv4/Ipv6 Dual-Stack Router Based on Debian 12

2024-03-24

Introduction

Recently, I bought a cheap mini host with an Intel Celeron processor. This host has two network interfaces, making it suitable as a router. Since my old router does not support IPv6, I decided to replace it with this machine. The original wireless router is now used only as an access point. Typically, one would use a operating system dedicated to routing, like OpenWRT, but since I also want self-host many services on this machine, Debian is more suitable for me, despite lacking a user-friendly web configuration interface for routing. I need to configure the routing function manually.

Here, I'll write about how to configure a functional router using Debian.

Basic Settings

This host has two network interfaces named enp2s0 and enp4s0. In theory, with VLAN, one network interface is enough to setup a router. However, according to my experience, VLAN-based single-arm routers are cumbersome. So, in pursuit of "less hassle", I recommend using two network interfaces. If there is only on network interface on the motherboard, you can purchase a USB 3.0 network card to add an extra network interface.

Here, I use enp2s0 as the wide area network (WAN) interface with IP addresses allocated by the ISP, and enp4s0 is the local area network (LAN) interface, with an IPv4 network of 192.168.31.0/24, and the address is 192.168.31.63; the IPv6 network on LAN is fc61:5887:1acd:4260::/64, and the address is fc61:5887:1acd:4260::1.

You can choose any IPv4 network segment in 192.168.*.*, as long as there are no conflicts. For IPv6, all network segments start with fc are private. I used a randomly generated 64-bit segment here.

WAN Configuration

Debian currently uses the "networking" service to configure networks. Edit /etc/network/interfaces and add:

allow-hotplug enp2s0
iface enp2s0 inet dhcp
iface enp2s0 inet6 dhcp

Then run:

sudo systemctl restart networking

LAN Configuration

Edit /etc/network/interfaces again and add:

allow-hotplug enp4s0
iface enp4s0 inet static
    address 192.168.31.63/24
iface enp4s0 inet6 static
    address fc61:5887:1acd:4260::1/64

Then run:

sudo systemctl restart networking

IP Forwarding

Edit /etc/sysctl.conf and add:

net.ipv4.ip_forward = 1
net.ipv6.conf.enp2s0.accept_ra = 2
net.ipv6.conf.all.forwarding=1

Apply and configurations:

sudo sysctl -p

I met trouble with IPv6 here. I don't know why the default route rule of IPv6 disappeared after me applying the configuration, and I failed to troubleshoot it. So I decided to add the routing rule manually:

sudo ip -6 route add default via fe80::1 dev enp2s0 proto ra metric 1024 hoplimit 255 pref medium

The routing rule may be different in various environments. So before enabling IPv6 forwarding, you can use this shell command to get current routing rule, which should be auto-configured by ISP:

sudo ip -6 route | grep default

Also, the manually added rules should be included in autostart script.

NAT

Linux's firewall configuration has shifted to nftables, but since I'm not familiar with nftables yet, I used the iptables compatibility layer instead.

IPv4 NAT configuration:

IPT=/usr/sbin/iptables
SUB_NET=192.168.31.0/24
WAN_FACE=enp2s0
LAN_FACE=enp4s0

$IPT -t nat -I POSTROUTING 1 -s $SUB_NET -o $WAN_FACE -j MASQUERADE
$IPT -I INPUT -i $LAN_FACE -j ACCEPT
$IPT -I FORWARD -i $WAN_FACE -o $LAN_FACE -j ACCEPT
$IPT -I FORWARD -i $LAN_FACE -o $WAN_FACE -j ACCEPT

IPv6 NAT configuration:

IPT=/usr/sbin/ip6tables
SUB_NET=fc61:5887:1acd:4260::/64
WAN_FACE=enp2s0

$IPT -t nat -A POSTROUTING -o $WAN_FACE -j MASQUERADE

These are bash scripts that should be added to an autostart script.

In theory, IPv6 doesn't need NAT. However, due to uncertainty about my ISP's IPv6 address allocation rules, I chose NAT for easier setup.

DHCP Server

Debian 12 provides isc-dhcp-server:

sudo apt install isc-dhcp-server

First, modify /etc/default/isc-dhcp-server; here, we only need IPv4:

INTERFACESv4="enp4s0"
INTERFACESv6=""

Then edit /etc/dhcp/dhcpd.conf:

option domain-name-servers 8.8.8.8;

subnet 192.168.31.0 netmask 255.255.255.0 {
  range 192.168.31.100 192.168.31.200;
  option routers 192.168.31.63;
}

For IPv6, DHCP is unnecessary; you can use IPv6 Stateless Address Autoconfiguration (SLAAC) directly. But you need to setup an autoconfiguration daemon. First, install radvd:

sudo apt install radvd

Then create the configuration '/etc/radvd.conf':

interface enp4s0 {
	AdvSendAdvert on;
	MinRtrAdvInterval 30;
	MaxRtrAdvInterval 100;
	prefix fc61:5887:1acd:4260::/64 {
		AdvOnLink on;
		AdvAutonomous on;
		AdvRouterAddr off;
	};
};

Finally, restart the DHCP server and radvd:

sudo systemctl restart isc-dhcp-server
sudo systemctl restart radvd

If these servers work correctly, the setup of the router is done.



Email: i (at) mistivia (dot) com