From 742a70b3d057ceb238560abbb0942f9411e19c37 Mon Sep 17 00:00:00 2001 From: "Jon C. Thomason" <2807816+jonct@users.noreply.github.com> Date: Fri, 5 Jul 2024 05:21:49 -0400 Subject: [PATCH] Add a simple router template (#216) * Add simple router example --------- Co-authored-by: Jip-Hop <2871973+Jip-Hop@users.noreply.github.com> --- templates/router/README.md | 44 ++++++++++++++ templates/router/config | 82 +++++++++++++++++++++++++++ templates/router/dnsmasq-example.conf | 50 ++++++++++++++++ 3 files changed, 176 insertions(+) create mode 100644 templates/router/README.md create mode 100644 templates/router/config create mode 100644 templates/router/dnsmasq-example.conf diff --git a/templates/router/README.md b/templates/router/README.md new file mode 100644 index 0000000..70912c5 --- /dev/null +++ b/templates/router/README.md @@ -0,0 +1,44 @@ +# Router Jail Template + +Host a subordinate LAN using nftables and dnsmasq for DHCP, DNS, routing, and netboot infrastructure. +``` +router laptop desktop + | | | + +-- LAN --+-------+ + | + { TrueNAS SCALE } + | + +-----+-----+-- LAN2 --+------+------+-------+ + | | | | | | | + RPi1 RPi2 RPi3 NUC01 NUC02 NUC03 CrayYMP +``` +*Example usage*: deploy a flock of headless/diskless Raspberry Pi worker nodes for Kubernetes; each netbooting into an iSCSI or NFS root volume. + +## Setup + +Use the TrueNAS SCALE administrative UI to create a network bridge interface. Assign to that bridge a physical interface that's not shared with the host network. + +Use the `dnsmasq-example.conf` file as a starting point for your own dnsmasq settings file(s). Copy or mount them inside `/etc/dnsmasq.d/` within the jail. + +Optional: place assets in the mounted `/tftp/` directory for netbooting clients. + +Optional: attach more jails to this same bridge to host e.g. a K3s control plane, an nginx load balancer, a PostgreSQL database... + +Check out the [config](./config) template file. You may provide it when asked during `./jlmkr.py create` or, if you have the template file stored on your NAS, you may provide it directly by running `./jlmkr.py create --start --config /mnt/tank/path/to/router/config myrouterjail`. + +## Additional Resources + +There are as many reasons to host LAN infrastructure as there are to connect a LAN. This template can help you kick-start such a leaf network, using a TrueNAS jail as its gateway host. + +For those specifically interested in *netbooting Raspberry Pi*, the following **external** links might help you get started. + +* [Network Booting a Raspberry Pi 4 with an iSCSI Root via FreeNAS][G1]; the title says it all +* [Raspberry Pi Network Boot Guide][G2] covers more Raspberry Pi models; written for Synology users +* [pi_iscsi_netboot][s1] and [prep-netboot-storage][s2] are scripts showing preparation of boot assets and iSCSI root volumes + +Good luck! + +[G1]: https://shawnwilsher.com/2020/05/network-booting-a-raspberry-pi-4-with-an-iscsi-root-via-freenas/ +[G2]: https://warmestrobot.com/blog/2021/6/21/raspberry-pi-network-boot-guide +[s1]: https://github.com/tjpetz/pi_iscsi_netboot +[s2]: https://gitlab.com/jnicpon/rpi-prep/-/blob/main/scripts/prep-netboot-storage.fish?ref_type=heads diff --git a/templates/router/config b/templates/router/config new file mode 100644 index 0000000..65b1cfa --- /dev/null +++ b/templates/router/config @@ -0,0 +1,82 @@ +# See also: +# +# +startup=0 +gpu_passthrough_intel=0 +gpu_passthrough_nvidia=0 +# Turning off seccomp filtering improves performance at the expense of security +seccomp=1 + +# Use bridge networking to provide an isolated network namespace +# Alternatively use --network-macvlan=eno1 instead of --network-bridge +# Ensure to change br0 to the HOST interface name you want to use +# and br1 to the SECONDARY interface name you want to prepare +# Substitute your own dnsmasq.d and TFTP dataset bindings +systemd_nspawn_user_args=--network-bridge=br0 + --network-veth-extra=ve-router-1:vee-1 + --resolv-conf=bind-host + --system-call-filter='add_key keyctl bpf' + --bind=/mnt/pool/subnet/dnsmasq.d:/etc/dnsmasq.d + --bind-ro=/mnt/pool/subnet/tftpboot:/tftp + +# Script to run on the HOST before starting the jail +# Load kernel module and config kernel settings required for podman +pre_start_hook=#!/usr/bin/bash + set -euo pipefail + echo 'PRE_START_HOOK' + echo 1 > /proc/sys/net/ipv4/ip_forward + modprobe br_netfilter + echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables + echo 1 > /proc/sys/net/bridge/bridge-nf-call-ip6tables + modprobe iptable_nat + modprobe iptable_filter + +# Script to run on the HOST after starting the jail +# For example to attach to multiple bridge interfaces +post_start_hook=#!/usr/bin/bash + set -euo pipefail + echo 'POST_START_HOOK' + ip link set dev ve-router-1 master br1 + ip link set dev ve-router-1 up + #ip link set dev eth2 master br1 + +# Only used while creating the jail +distro=debian +release=bookworm + +# Install and configure within the jail +initial_setup=#!/usr/bin/bash + set -euo pipefail + + # Catch up on updates + apt-get update && apt-get full-upgrade -y + + # Configure worker LAN interface with static IP + sh -c 'cat < /etc/systemd/network/80-container-vee-1.network + [Match] + Virtualization=container + Name=vee-1 + + [Network] + DHCP=false + Address=10.3.14.202/24 + EOF' + systemctl restart systemd-networkd.service + + # Configure routing from LAN clients + apt-get install nftables -y + nft add table nat + nft add chain nat prerouting { type nat hook prerouting priority 0 \; } + nft add chain nat postrouting { type nat hook postrouting priority 100 \; } + nft add rule nat postrouting masquerade + mkdir -p /etc/nftables.d + nft list table nat >/etc/nftables.d/nat.conf + ( echo ; echo 'include "/etc/nftables.d/*.conf"' ) >>/etc/nftables.conf + + # Install dnsmasq alongside local resolver + sed -i -e 's/^#DNSStubListener=yes$/DNSStubListener=no/' /etc/systemd/resolved.conf + systemctl restart systemd-resolved.service + apt-get install dnsmasq -y + sed -i -e 's/^#DNS=$/DNS=127.0.0.1/' /etc/systemd/resolved.conf + systemctl restart systemd-resolved.service + systemctl restart dnsmasq.service diff --git a/templates/router/dnsmasq-example.conf b/templates/router/dnsmasq-example.conf new file mode 100644 index 0000000..fee9a4e --- /dev/null +++ b/templates/router/dnsmasq-example.conf @@ -0,0 +1,50 @@ +# customize and place this file inside /etc/dnsmasq.d + +# serve only Raspberry Pi network; don't backfeed to the host LAN +no-dhcp-interface=host0 +interface=vee-1 +bind-interfaces + +# designated upstream query servers +server=1.1.1.1 +server=1.0.0.1 + +# pirate TLD for the Democratic Republic of Raspberry Pi +domain=pi,10.3.14.0/24 + +# enable DHCP services +dhcp-authoritative +dhcp-rapid-commit +dhcp-range=10.3.14.101,10.3.14.199 + +# meet the 'berries +dhcp-host=e4:5f:01:da:da:b1,rpi1,10.3.14.11,infinite,set:rpi +dhcp-host=e4:5f:01:da:da:b2,rpi2,10.3.14.12,infinite,set:rpi +dhcp-host=e4:5f:01:da:da:b3,rpi3,10.3.14.13,infinite,set:rpi +dhcp-host=e4:5f:01:da:da:b4,rpi4,10.3.14.14,infinite,set:rpi +dhcp-host=e4:5f:01:da:da:b5,rpi5,10.3.14.15,infinite,set:rpi +dhcp-host=e4:5f:01:da:*:*,set:rpicube + +# PXE +dhcp-option-force=66,10.3.14.202 +# magic number +dhcp-option-force=208,f1:00:74:7e +# config filename +dhcp-option-force=209,configs/common +# path prefix +dhcp-option-force=210,/boot/ +# reboot time (i -> 32 bit) +dhcp-option-force=211,30i + +dhcp-boot=bootcode.bin + +#dhcp-match=set:ipxe,175 +#dhcp-boot=tag:ipxe,http://boot.netboot.xyz/ipxe/netboot.xyz.efi + +# TFTP +enable-tftp +tftp-root=/tftp + +#debugging +#log-queries +#log-dhcp