Created
January 14, 2022 18:37
-
-
Save Emantor/77b4f59221cc4ab327de749660548841 to your computer and use it in GitHub Desktop.
router.nix
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Edit this configuration file to define what should be installed on | |
# your system. Help is available in the configuration.nix(5) man page | |
# and in the NixOS manual (accessible by running ‘nixos-help’). | |
{ config, pkgs, ... }: | |
{ | |
imports = | |
[ # Include the results of the hardware scan. | |
./hardware-configuration.nix | |
../../profiles | |
]; | |
# This is an APU2C4, enable serial output. | |
boot.kernelParams = [ "console=ttyS0,115200n8" ]; | |
# Flowtables for physical interfaces only work in 5.13+ | |
boot.kernelPackages = pkgs.linuxPackages_latest; | |
# Use the GRUB 2 boot loader. | |
boot.loader.grub.enable = true; | |
boot.loader.grub.version = 2; | |
boot.loader.grub.device = "/dev/sda"; | |
# This is an APU2C4, enable serial grub2 output. | |
boot.loader.grub.extraConfig = " | |
serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1 | |
terminal_input serial | |
terminal_output serial | |
"; | |
# boot.loader.grub.efiSupport = true; | |
# boot.loader.grub.efiInstallAsRemovable = true; | |
# boot.loader.efi.efiSysMountPoint = "/boot/efi"; | |
# Define on which hard drive you want to install Grub. | |
# boot.loader.grub.device = "/dev/sda"; # or "nodev" for efi only | |
networking.hostName = "pseudopolisyard"; # Define your hostname. | |
networking.domain = "discworld.emantor.de"; # Define your domain. | |
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. | |
# Set your time zone. | |
# time.timeZone = "Europe/Amsterdam"; | |
# The global useDHCP flag is deprecated, therefore explicitly set to false here. | |
# Per-interface useDHCP will be mandatory in the future, so this generated config | |
# replicates the default behaviour. | |
environment.systemPackages = with pkgs; [ | |
conntrack-tools | |
]; | |
networking = { | |
useDHCP = false; | |
nat.enable = false; | |
firewall.enable = false; | |
nftables = { | |
enable = true; | |
ruleset = '' | |
table inet filter { | |
# enable flow offloading for better throughput | |
flowtable f { | |
hook ingress priority 0; | |
devices = { enp2s0, enp1s0 }; | |
} | |
chain output { | |
type filter hook output priority 100; policy accept; | |
oifname "lo" ip6 daddr != ::1/128 log prefix "Dropped IPv6 nonlocalhost packet on loopback:" drop | |
oifname "ppp0" ip6 daddr fe80::/10 icmpv6 type echo-request ct state new,established accept | |
} | |
chain input { | |
type filter hook input priority 0; policy drop; | |
ct state {established, related} counter accept comment "accept all connections related to connections made by us" | |
ct state invalid counter drop comment "early drop of invalid packets" | |
# Allow trusted networks to access the router | |
iif "enp1s0" counter accept | |
iif "enp2s0" counter accept | |
iifname "guest.100*" counter accept | |
iifname "devices.300*" counter accept | |
iifname "wg-roadwarrior" counter accept | |
# DHCPv6 | |
meta nfproto ipv6 udp sport 547 accept comment "DHCPv6 client" | |
# Wireguard | |
meta nfproto ipv4 udp dport 51820 accept comment "Wireguard" | |
# Allow ICMP | |
ip protocol icmp counter accept comment "accept all ICMP types" | |
ip6 nexthdr icmpv6 counter accept comment "accept all ICMP types" | |
# Accept loopback traffic | |
iif lo accept comment "Accept Loopback traffic" | |
# Allow returning traffic from ppp0 and drop everthing else | |
iifname "ppp0" ct state established,related counter accept | |
iifname "ppp0" drop | |
iifname "lo" ip6 saddr != ::1/128 log prefix "Dropped IPv6 nonlocalhost packet on loopback:" drop | |
} | |
chain forward { | |
type filter hook forward priority 0; policy drop; | |
tcp flags syn tcp option maxseg size set rt mtu | |
ct status dnat counter accept | |
# enable flow offloading for better throughput | |
# currently broken, needs further investigation | |
# ip protocol { tcp, udp } flow offload @f | |
# Forward ICMPv6 | |
icmpv6 type echo-request limit rate 5/second counter accept | |
icmpv6 type echo-request counter drop | |
meta l4proto ipv6-icmp accept | |
# Allow trusted network WAN access | |
iif "enp1s0" counter accept comment "Allow all traffic forwarding from LAN " | |
iif "enp2s0" counter accept comment "Allow VDSL router forwarding" | |
iifname "wg-roadwarrior" counter accept comment "Allow all traffic forwarding from Wireguard" | |
iifname "guest.100*" oifname "ppp0" counter accept comment "Allow trusted Guest to WAN" | |
# Allow established WAN to return | |
iifname "ppp0" oif "enp1s0" ct state established,related counter accept comment "Allow established back to LANs" | |
iifname "ppp0" oifname "wg-roadwarrior" ct state established,related counter accept comment "Allow established back to Wireguard" | |
iifname "ppp0" oifname "guest.100*" ct state established,related counter accept comment "Allow established back to Guest" | |
} | |
} | |
table ip nat { | |
chain prerouting { | |
type nat hook prerouting priority -100; policy accept; | |
iifname "ppp0" tcp dport 53 dnat to 192.168.128.220 | |
iifname "ppp0" udp dport 53 dnat to 192.168.128.220 | |
} | |
# Setup NAT masquerading on the ppp0 interface | |
chain postrouting { | |
type nat hook postrouting priority 100; policy accept; | |
oifname "ppp0" masquerade | |
} | |
} | |
table arp filter { | |
chain input { | |
type filter hook input priority 0; policy accept; | |
iif enp1s0 limit rate 1/second burst 2 packets accept | |
} | |
chain output { | |
type filter hook output priority 0; policy accept; | |
} | |
} | |
''; | |
}; | |
}; | |
# Configure network proxy if necessary | |
# networking.proxy.default = "http://user:password@proxy:port/"; | |
# networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; | |
# Select internationalisation properties. | |
# i18n.defaultLocale = "en_US.UTF-8"; | |
# console = { | |
# font = "Lat2-Terminus16"; | |
# keyMap = "us"; | |
# }; | |
# Enable the X11 windowing system. | |
# services.xserver.enable = true; | |
# Configure keymap in X11 | |
# services.xserver.layout = "us"; | |
# services.xserver.xkbOptions = "eurosign:e"; | |
# Enable CUPS to print documents. | |
# services.printing.enable = true; | |
# Enable sound. | |
# sound.enable = true; | |
# hardware.pulseaudio.enable = true; | |
# Enable touchpad support (enabled default in most desktopManager). | |
# services.xserver.libinput.enable = true; | |
# Define a user account. Don't forget to set a password with ‘passwd’. | |
# users.users.jane = { | |
# isNormalUser = true; | |
# extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. | |
# }; | |
# List packages installed in system profile. To search, run: | |
# $ nix search wget | |
# environment.systemPackages = with pkgs; [ | |
# vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. | |
# wget | |
# firefox | |
# ]; | |
# Some programs need SUID wrappers, can be configured further or are | |
# started in user sessions. | |
# programs.mtr.enable = true; | |
# programs.gnupg.agent = { | |
# enable = true; | |
# enableSSHSupport = true; | |
# }; | |
# List services that you want to enable: | |
# Enable the OpenSSH daemon. | |
services.openssh.enable = true; | |
services.resolved = { | |
enable = true; | |
domains = [ "discworld.emantor.de" ]; | |
}; | |
networking.nameservers = [ "127.0.0.1" ]; | |
systemd.network = { | |
enable = true; | |
netdevs = { | |
"devices.300" = { | |
netdevConfig = { | |
Kind = "vlan"; | |
Name = "devices.300"; | |
}; | |
vlanConfig = { | |
Id = 300; | |
}; | |
}; | |
"guest.100" = { | |
netdevConfig = { | |
Kind = "vlan"; | |
Name = "guest.100"; | |
}; | |
vlanConfig = { | |
Id = 100; | |
}; | |
}; | |
}; | |
networks = { | |
"ppp" = { | |
name = "ppp*"; | |
networkConfig = { | |
KeepConfiguration = "static"; | |
DefaultRouteOnDevice = true; | |
LinkLocalAddressing = "ipv6"; | |
DHCP = "ipv6"; | |
}; | |
dhcpV6Config = { | |
ForceDHCPv6PDOtherInformation = true; | |
PrefixDelegationHint= "::/56"; | |
}; | |
extraConfig = '' | |
[CAKE] | |
OverheadBytes = 65 | |
Bandwidth = 40M | |
''; | |
}; | |
"enp1s0" = { | |
name = "enp1s0"; | |
networkConfig = { | |
Address = "192.168.128.254/24"; | |
Domains = "discworld.emantor.de"; | |
VLAN = [ "devices.300" "guest.100" ]; | |
EmitLLDP = "yes"; | |
IPv6SendRA = true; | |
DHCPv6PrefixDelegation = true; | |
}; | |
dhcpV6PrefixDelegationConfig = { | |
SubnetId = "0x1"; | |
}; | |
ipv6Prefixes = [ | |
{ | |
ipv6PrefixConfig.Prefix = "fd66:a562:1af6:1::/64"; | |
} | |
]; | |
extraConfig = '' | |
[CAKE] | |
OverheadBytes = 38 | |
Bandwidth = 1G | |
''; | |
}; | |
"enp2s0" = { | |
name = "enp2s0"; | |
networkConfig = { | |
Address = "192.168.1.254/24"; | |
EmitLLDP = "yes"; | |
}; | |
}; | |
"devices.300" = { | |
name = "devices.300"; | |
networkConfig = { | |
Address = "172.16.128.254/24"; | |
EmitLLDP = "yes"; | |
IPv6SendRA = false; | |
}; | |
ipv6Prefixes = [ | |
{ | |
ipv6PrefixConfig.Prefix = "fd66:a562:1af6:300::/64"; | |
} | |
]; | |
}; | |
"guest.100" = { | |
name = "guest.100"; | |
networkConfig = { | |
Address = "192.168.120.254/24"; | |
EmitLLDP = "yes"; | |
IPv6SendRA = true; | |
DHCPv6PrefixDelegation = true; | |
}; | |
dhcpV6PrefixDelegationConfig = { | |
SubnetId = "0x2"; | |
}; | |
ipv6Prefixes = [ | |
{ | |
ipv6PrefixConfig.Prefix = "fd66:a562:1af6:100::/64"; | |
} | |
]; | |
}; | |
}; | |
}; | |
# Forwarding configuration | |
boot.kernel.sysctl = { | |
# if you use ipv4, this is all you need | |
"net.ipv4.conf.all.forwarding" = true; | |
# If you want to use it for ipv6 | |
"net.ipv6.conf.all.forwarding" = true; | |
# source: https://github.com/mdlayher/homelab/blob/master/nixos/routnerr-2/configuration.nix#L52 | |
# By default, not automatically configure any IPv6 addresses. | |
"net.ipv6.conf.all.accept_ra" = 0; | |
"net.ipv6.conf.all.autoconf" = 0; | |
"net.ipv6.conf.all.use_tempaddr" = 0; | |
}; | |
# PPPoE | |
services.pppd = { | |
enable = true; | |
peers = { | |
einsundeins = { | |
# Autostart the PPPoE session on boot | |
autostart = true; | |
enable = true; | |
config = '' | |
plugin rp-pppoe.so enp2s0 | |
# pppd supports multiple ways of entering credentials, | |
# this is just 1 way | |
name "<username>" | |
persist | |
maxfail 0 | |
holdoff 5 | |
noipdefault | |
defaultroute | |
''; | |
}; | |
}; | |
}; | |
# DNS | |
services.unbound = { | |
enable = true; | |
settings = { | |
server = { | |
access-control = [ | |
"127.0.0.0/8 allow" | |
"127.0.0.1/32 allow_snoop" | |
"192.168.128.0/23 allow" | |
"192.168.120.0/24 allow" | |
"172.16.128.0/24 allow" | |
"::1/128 allow_snoop" | |
]; | |
interface = ["127.0.0.1" "192.168.128.254" "172.16.128.254" "192.168.120.254" "::1"]; | |
val-permissive-mode = "yes"; | |
module-config = "iterator"; | |
local-zone = [ | |
"\"168.192.in-addr.arpa.\" nodefault" | |
"\"d.f.ip6.arpa.\" nodefault" | |
]; | |
}; | |
forward-zone = let | |
fwZone = name: addrs: { name = "${name}"; forward-addr = addrs; }; | |
in | |
[ | |
(fwZone "." [ "8.8.8.8" "8.8.4.4" ]) | |
]; | |
stub-zone = let | |
stubZone = name: addrs: { name = "${name}"; stub-addr = addrs; }; | |
in | |
[ | |
(stubZone "discworld.emantor.de" ["192.168.128.220"]) | |
(stubZone "6.f.a.1.2.6.5.a.6.6.d.f.ip6.arpa" ["192.168.128.220"]) | |
(stubZone "168.192.in-addr.arpa" ["192.168.128.220"]) | |
]; | |
}; | |
}; | |
# DHCP | |
services.dhcpd4 = { | |
enable = true; | |
interfaces = [ "enp1s0" "guest.100" "devices.300"]; | |
extraConfig = '' | |
ddns-update-style none; | |
subnet 192.168.128.0 netmask 255.255.255.0 { | |
range 192.168.128.100 192.168.128.200; | |
option routers 192.168.128.254; | |
option ntp-servers 192.168.128.254; | |
option domain-name-servers 192.168.128.254; | |
option domain-name "discworld.emantor.de"; | |
} | |
subnet 172.16.128.0 netmask 255.255.255.0 { | |
range 172.16.128.100 172.16.128.200; | |
option routers 172.16.128.254; | |
option ntp-servers 172.16.128.254; | |
option domain-name-servers 172.16.128.254; | |
option domain-name "devices.discworld.emantor.de"; | |
} | |
subnet 192.168.120.0 netmask 255.255.255.0 { | |
range 192.168.120.100 192.168.120.200; | |
option routers 192.168.120.254; | |
option ntp-servers 192.168.120.254; | |
option domain-name-servers 192.168.120.254; | |
option domain-name "guest.discworld.emantor.de"; | |
} | |
''; | |
}; | |
# NTP | |
services.chrony = { | |
enable = true; | |
extraConfig = '' | |
allow 192.168.128 | |
allow 172.16.128 | |
allow 192.168.120 | |
allow 192.168.1 | |
''; | |
}; | |
systemd.services.restart-ppp = { | |
enable = true; | |
unitConfig = { | |
Description = "Restart pppd-einsundeins service"; | |
}; | |
serviceConfig = { | |
Type = "oneshot"; | |
ExecStart= [ "${pkgs.systemd}/bin/systemctl restart pppd-einsundeins.service" ]; | |
}; | |
}; | |
systemd.timers.restart-ppp = { | |
unitConfig = { | |
Description = "PPP restart in the night"; | |
}; | |
timerConfig = { | |
OnCalendar = [ "*-*-* 4:00:00" ]; | |
}; | |
wantedBy = [ "default.target" ]; | |
}; | |
# DDNS | |
services.ddclient = { | |
enable = true; | |
use = "web, web=http://ipv4.stratum0.net/myip"; | |
ssl = true; | |
server = "ipv4.stratum0.net"; | |
username = "discworld.stratum0.net"; | |
domains = [ "discworld.stratum0.net" ]; | |
passwordFile = "/var/keys/ddns-stratum0"; | |
}; | |
# Wireguard | |
networking.wg-quick.interfaces = { | |
wg-roadwarrior = { | |
address = [ "192.168.129.254/24" ]; | |
privateKeyFile = "/var/keys/wg-roadwarrior"; | |
listenPort = 51820; | |
peers = [{ | |
allowedIPs = [ "192.168.129.12/32" ]; | |
publicKey = "FiwOiRnnMNlTf8nSlIqdzZXWBvbx8WIVAvbi7b/HHE0="; | |
}{ | |
allowedIPs = [ "192.168.129.11/32" ]; | |
publicKey = "OoaatUQ37OI1HnKNYavgDcp84fF5Ze3k1Q2ELsoqrA0="; | |
}{ | |
allowedIPs = [ "192.168.129.10/32" ]; | |
publicKey = "Zd0Y+IeApNqd0j22XrYWDAbEwfxObqnNxFDFBNbs70Q="; | |
}]; | |
}; | |
}; | |
# This value determines the NixOS release from which the default | |
# settings for stateful data, like file locations and database versions | |
# on your system were taken. It‘s perfectly fine and recommended to leave | |
# this value at the release version of the first install of this system. | |
# Before changing this value read the documentation for this option | |
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). | |
system.stateVersion = "21.11"; # Did you read the comment? | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment