06 April, 2022

Configuring systemd-networkd with a dual stack IPv4 and IPv6 ISP

General

This post is about connecting a Debian client to a 'generic' IPv4/IPv6 ISP. It was tested on Aussie Broadband, but this should work with most ISPs who offer IPv6 and use conventional edge-routers to provide IPv4 and IPv6 dual services.

Hardware

My interface machine is a NanoPi R2S Dual Gigabit router


The R2S is highly capable for the application but does run hot, so the R2S combo case is a necessity.

With the combo case the machine runs without issue in ambient room temperature of up to 35C without fans or other cooling.

System

The installed system is armbian that reports itself as debian.

root@firewall:~# cat /etc/os-release

PRETTY_NAME="Debian GNU/Linux 10 (buster)"

I am using buster, but  bullseye should work fine.

To make sure the network configuration is only controlled by systemd-networkd it is necessary to make sure that the competitor network configurator networking.service is restricted to only managing loopback and NetworkManager.service is completely disabled.

root@firewall:~# nano /etc/network/interfaces.default

auto lo

iface lo inet loopbackspan



root@firewall:~# cp /etc/network/interfaces /etc/network/interfaces.bak

root@firewall:~# cp /etc/network/interfaces.default /etc/network/interfaces

root@firewall:~# systemctl stop networking.service

root@firewall:~# rm -f /var/lib/dhcp/dhclient*

root@firewall:~# systemctl start networking.service

root@firewall:~# systemctl stop NetworkManager.service

root@firewall:~# systemctl mask NetworkManager.service

I have found that the systemd.resolved caching DNS service is unreliable. However there are ways to avoid using the actual caching server while maintaining some features of systemd-resolved and running a bind instance as well.

This is done by linking /etc/resolv. conf to /run/systemd/resolve/resolv.conf

This then allows the router dhcp client to modify things like DNS servers, using /etc/systemd/resoved.conf as a base.

root@firewall:~# mv /etc/resolv.conf /etc/bak_resolv.conf

root@firewall:~# ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf

root@firewall:~# cat /etc/systemd/resolved.conf

# This file is part of systemd.

#

# systemd is free software; you can redistribute it and/or modify it

# under the terms of the GNU Lesser General Public License as published by

# the Free Software Foundation; either version 2.1 of the License, or

# (at your option) any later version.

#

# Entries in this file show the compile time defaults.

# You can change settings by editing this file.

# Defaults can be restored by simply deleting this file.

#

# See resolved.conf(5) for details

[Resolve]

Domains=lan example.com

# Use bind instance on localhost for primary name service

# Then use a cloudflare server

DNS=::1 1.1.1.1;

LLMNR=true

MulticastDNS=true

DNSSEC=allow-downgrade

DNSOverTLS=false

Cache=yes

DNSStubListener=yes

ReadEtcHosts=yes

WAN configuration

The WAN interface is labelled eth0 in the standard armbian distribution for the R2S. The LAN interface is lan0. The configuration below starts an IPv4 DHCP client, an IPv6 DHCP client, and solicits an IPv6 Route Advertisement (RA) from the ISP router in order to be granted an IPv6 subnet sized /56 and have that network routed to this router.

At the end of the handshake procedure, the WAN interface will have a single IPv4 address and  a single IPv6 address, and will have a /56 IPv6 sub net routed to it. The WAN interface having received the IPv6 RA then makes it available for other systemd-networkd processes to advertise and allocate IPv6 address to the LAN.

The line IPForward=yes means  that IPv6 traffic will be forwarded from the WAN to the LAN and vice-versa. This means that an IP firewall is required on the router and/or on LAN machines. I prefer to have firewalling done on the router rather than trust individual LAN machines to do it correctly

root@firewall:~# cat /etc/systemd/network/eth0.network

[Match]

# Simple match on udev interface name

# Many other matches possible

# Searches in /etc/systemd

/n

etwork for a filename eth0.network

Name=eth0

[Network]

# Request an IPv4 Address and an IPv6 address from ISP router

DHCP=yes

# Accept an IPv6 Router Advertisement (RA) and use that to

# provide IPv6 subnet addresses to the LAN interface

IPv6AcceptRA=yes

# Enables link-local address autoconfiguration.

# This is in addition to any static addresses or DHCP addresses

# link-local address range is IPv6 fe80::/10 and is generated

# using the interface MAC address

LinkLocalAddressing=ipv6

# Allow IPv6 traffic from LAN and WAN and vice versa to be forwarded

# /etc/iptables/rules.v6 will be applied to any ipv6 traffic

#

# IPv4 addresses are subject to /etc/iptables/rules.v4 including NAT

IPForward=yes

# Parameters to be used when an IPv6 RA is received

[IPv6AcceptRA]

# Force starting the DHCPv6 client even if the Router Advertisement

# indicates it's not required.

DHCPv6Client=yes

# Parameters to be used when IPv6 is being used

[DHCPv6]

# Request upstream server provide a prefix RA and to route that

# prefix to this connection

#

# In general, connections to an upstream server won't work without

# this set to solicit

WithoutRA=solicit

LAN configuration

The LAN is configured to operate in IPv4 mode with NAT and IPv6 mode.

root@firewall:~# cat /etc/systemd/network/lan0.network

[Match]

# Simple match on udev interface name

# Many other matches possible

# Searches in /etc/systemd/network for a file .network

Name=lan0

[Network]

# Address is a static IPv4 or IPv6 address and its prefix length,

# separated by a "/" character.

#

# Specify this key more than once to configure several addresses.

# The format of the address must be as described in inet_pton(3).

# This is a short-hand for an [Address]section only containing an

# Address key (see below).

# This option may be specified more than once.

# Use of these addresses in LAN and WAN is managed by

# /etc/iptables/rules.v4

# .1 is used for router gateway as it's easy to remember

Address=192.168.1.1/24

# Other addresses for specific purposes such as DNS

Address=192.168.1.5/24

# Assign fixed IPv6 addresses to interface.

# Configuration here is static and will vary depending on the

# IPv6 addresses/ranges provided by the upstream server.

# Internet clients can access addresses via the the iptables

# routing / screening set up in /etc/iptables/rules.v6

# Primary fixed IPv6 address on LAN

Address=2001:db8:ADD0:AD00::1/64

# Assign additional IPv6 addresses on LAN

Address=2001:db8:ADD0:AD00::5/64

# Sets the order for searching DNS names. e.g. 'client' is

# searched as 'client.lan' then 'client.example.com'

# These domains are also given to clients using the IPv6 RA

Domains=lan example.com

# Use link-local address autoconfiguration for IPv6 range fe80::/10

# It uses MAC address to generate specific link local address

# This address is in addition to any fixed addresses specified

LinkLocalAddressing=ipv6

# This says don't listen for IPv6 route advertisments on the LAN

# because this machine is the master that issues advertisements.

IPv6AcceptRA=no

# Announce a prefix.

# clients listen for the advertisement and can configure their own

# IPv6 addresses or use DHCPv6 to get allocated addresses

IPv6SendRA=yes

# Use DHCPv6-PD delegated prefix (DHCPv6PrefixDelegation.SubnetId)

# and advertise to this network.

DHCPv6PrefixDelegation=yes

# The [DHCPv6PrefixDelegation] section configures delegated

# prefixes assigned by the ISP router. The settings in this

# section are used only when DHCPv6PrefixDelegation=yes

[DHCPv6PrefixDelegation]

# Configure a specific subnet ID on the interface from a

# previously received prefix delegation. You can either

# set "auto" (the default) or a specific subnet ID

# (as # defined in RFC 4291[21], section 2.5.4),

# in which case the allowed value is hexadecimal,

# from 0 to 0x7fffffffffffffff inclusive.

# Design is for a /56 subnet so there are 256 /64

# sub-subnets 00 to FF

SubnetId=0x00

# When Announce=yes and IPv6SendRA=yes in [Network] section

# the delegated prefixes are distributed through the

# IPv6 Router Advertisement.

Announce=yes

# Data to send in the RA

[IPv6SendRA]

# Inform clients there is a DHCPv6 server on the LAN

Managed=true

# Inform clients of a DNS server (on this machine)

EmitDNS=true

# Tell clients to use IPv6 link local addressing to access

# a DNS server on this machine

# This requires this machine to be running a DNS server

# - typically bind

DNS=_link_local

iptables configuration

iptables is used to provide NAT functions for lan IPv4 clients and to provide routing and firewall functions for IPv4 and IPv6

root@firewall:~# cat /etc/iptables/rules.v4

*filter

:INPUT ACCEPT [0:0]

:FORWARD ACCEPT [0:0]

:OUTPUT ACCEPT [269:33668]

# Rules for access to this machine are governed by

# INPUT and OUTPUT rule chains

# All traffic from LAN is accepted as well as all icmp

# and all localhost traffic

-A INPUT -i lan0 -j ACCEPT

-A INPUT -p icmp -j ACCEPT

-A INPUT -i lo -j ACCEPT

# This section is for internet facing IPv4 services on this machine

-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

-A INPUT -p tcp -m tcp --dport 25 -j ACCEPT

-A INPUT -p udp -m udp --dport 53 -j ACCEPT

-A INPUT -p tcp -m tcp --dport 53 -j ACCEPT

-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT

-A INPUT -p tcp -m tcp --dport 143 -j ACCEPT

-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT

-A INPUT -p tcp -m tcp --dport 465 -j ACCEPT

-A INPUT -p tcp -m tcp --dport 587 -j ACCEPT

-A INPUT -p tcp -m tcp --dport 993 -j ACCEPT

-A INPUT -j DROP

# FORWARD rules are for WAN to LAN and LAN to WAN traffic

# Rules establish a NAT for non routable LAN hosts to

# access the internet

-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

-A FORWARD -s 192.168.1.0/24 -i lan0 -m conntrack --ctstate NEW -j ACCEPT

COMMIT

# Configuration for nat

*nat

:PREROUTING ACCEPT [0:0]

:INPUT ACCEPT [0:0]

:OUTPUT ACCEPT [0:0]

:POSTROUTING ACCEPT [0:0]

-A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE

COMMIT

root@firewall:~# cat /etc/iptables/rules.v6

*filter

:INPUT ACCEPT [0:0]

:FORWARD ACCEPT [0:0]

:OUTPUT ACCEPT [0:0]

:server_in - [0:0]

# Access to services on this machine from Internet and LAN

-A INPUT -m rt --rt-type 0 -j DROP

-A INPUT -i lo -j ACCEPT

-A INPUT -i lan0 -j ACCEPT

-A INPUT -i lo -j ACCEPT

-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

-A INPUT -s fe80::/10 -j ACCEPT

-A INPUT -d ff00::/8 -j ACCEPT

-A INPUT -p ipv6-icmp -j ACCEPT

-A INPUT -p tcp -m tcp -j server_in

-A INPUT -p udp -m udp -j server_in

-A INPUT -j DROP

# Access to services on LAN and IP addresses on this machine's

# LAN interface

# General rule is allow all outbound LAN traffic, but this

# could be tightened

-A FORWARD -m rt --rt-type 0 -j DROP

-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

-A FORWARD -p ipv6-icmp -j ACCEPT

-A FORWARD -s 2001:db8:ADD0:AD00::/56 -i lan0 -j ACCEPT

# Address range for general internet servers /120 subnet of /56

# bottom most 256 addresses of prefix are permitted after filtering

-A FORWARD -d 2001:db8:ADD0:AD00::/120 -i eth0 -j server_in

-A FORWARD -j DROP

-A OUTPUT -m rt --rt-type 0 -j DROP

-A OUTPUT -j ACCEPT

# General server chain

-A server_in -p tcp -m tcp --dport 25 -j ACCEPT

-A server_in -p udp -m udp --dport 53 -j ACCEPT

-A server_in -p tcp -m tcp --dport 53 -j ACCEPT

-A server_in -p tcp -m tcp --dport 80 -j ACCEPT

-A server_in -p tcp -m tcp --dport 143 -j ACCEPT

-A server_in -p tcp -m tcp --dport 443 -j ACCEPT

-A server_in -p tcp -m tcp --dport 587 -j ACCEPT

-A server_in -p tcp -m tcp --dport 993 -j ACCEPT

COMMIT

No comments:

Post a Comment

Configuring systemd-networkd with a dual stack IPv4 and IPv6 ISP

General This post is about connecting a Debian client to a 'generic' IPv4/IPv6 ISP. It was tested on Aussie Broadband, but this shou...