From 444aa962b5159b577598b19382de3407d21a29a5 Mon Sep 17 00:00:00 2001 From: Simon Bruder Date: Sun, 2 Apr 2023 01:14:01 +0200 Subject: [PATCH] fuuko: Add router service MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This now mostly replaces ayu, which has been sitting between upstream and the switch the last 6 months. It now also configures routing over Mullvad, which also finally enables IPv6 (I don’t understand how people get away with not providing it natively in 2023). Once I get a WLAN card, it will also host its own access point, which currently still relies on ayu as “dumb AP” (as OpenWRT calls it). --- machines/fuuko/configuration.nix | 1 + machines/fuuko/hardware-configuration.nix | 5 - machines/fuuko/secrets.yaml | 5 +- machines/fuuko/services/router.nix | 215 ++++++++++++++++++++++ machines/renge/services/prometheus.nix | 8 + 5 files changed, 227 insertions(+), 7 deletions(-) create mode 100644 machines/fuuko/services/router.nix diff --git a/machines/fuuko/configuration.nix b/machines/fuuko/configuration.nix index 8190f0b..7c0fc07 100644 --- a/machines/fuuko/configuration.nix +++ b/machines/fuuko/configuration.nix @@ -9,6 +9,7 @@ ./services/languagetool.nix ./services/media-backup.nix ./services/media.nix + ./services/router.nix ./services/torrent.nix ]; diff --git a/machines/fuuko/hardware-configuration.nix b/machines/fuuko/hardware-configuration.nix index 7196d49..68eb561 100644 --- a/machines/fuuko/hardware-configuration.nix +++ b/machines/fuuko/hardware-configuration.nix @@ -75,11 +75,6 @@ powerManagement.cpuFreqGovernor = "schedutil"; - networking = { - useDHCP = false; - interfaces.enp8s0.useDHCP = true; - }; - services.logind.extraConfig = '' HandlePowerKey=suspend ''; diff --git a/machines/fuuko/secrets.yaml b/machines/fuuko/secrets.yaml index 8ac2d2f..9edbd4f 100644 --- a/machines/fuuko/secrets.yaml +++ b/machines/fuuko/secrets.yaml @@ -1,5 +1,6 @@ restic-ssh-key: ENC[AES256_GCM,data:wA7JCg6Y900s6+1JoevMzbr6fKRN6jbfUuX166VS+TUFhFbn0npz5gKkAQpC8h1io1WaSCPJkJMzr+viOLlnVwqe8zFGm3ZJlKSEqKKK+CatZ95+zKACOZuBAC/2E6rep6JnL/C3/gKMKibVmAL+9TkTX6nA83xwhM65JPLN/+bP29bq0Cr2FopgZgNPQjb6ANB4POy+MUktet63DZ4dJwKvndiCRg4EMLIOqFopbQei6Pxc1F/lC3yBu71YgB4TSGQp/6tXjfFOuXQpI0nFrZCmLYcW03ZqOBQbKg3w4rwlqtnl25/23jpT0kqWp99wHUGMCib5+iywPUMSNDwAsz0fq04JGpTEM9cuxkLWZVfCpguNlgaiwCObyJkA2CHXlIn6KYsDOa6U/Uy9mNRPae52j/E+JdLQycOwT5+n78j0vqtvS69blUC/E7j2IWe17SI8JVCiYFbZXPqVm43jdEiQ9jU4gXMsu6NKppnBhFSrMVUHScS3gR/xnTfrabrr2FWJwIOjdGdJb4pr+nfZ,iv:ow+hzt5YGGD0FDvN+XkZtW74k4mwW+6HqWZMtOwAWDg=,tag:HXogIkcSTq6Ep4M2MXEMew==,type:str] wg-home-private-key: ENC[AES256_GCM,data:6l3CgB4qCsPuyYOWuwU2vNiEeC0D1wl6yZvXGGYVsZfYvdPjRz8j5yV7ekQ=,iv:slB/qr+cxi8r7cnTuZAd8CuzWVnvp24Li6A/AnZaFzo=,tag:ynh1Z2+IELAJcgBbHwFC0A==,type:str] +wg-mullvad-private-key: ENC[AES256_GCM,data:4smAYjzrMz6bapthHwTdeDJSvnEqnGmDFRZjJwnXWXLSYnEhzhvRttVrmFw=,iv:94o7E8IlZ6V+wez5+Zr9xv92rr06MlUfBCvtMW8VnEA=,tag:SJjrbBseVyWwhf9IHRi7rQ==,type:str] wg-qbittorrent-private-key: ENC[AES256_GCM,data:9sjqTCMXqN0oWS95RQOmfLK0/2dH6V4Rs2LX8ydnYl+7zR55PG5pW3kROH8=,iv:m+4xKthKNCQBOEP9ExOHY5Dg3i+yTgREwrAci4zhqUk=,tag:L0vnwyiGOAoarr7FZFE91A==,type:str] sops: kms: [] @@ -7,8 +8,8 @@ sops: azure_kv: [] hc_vault: [] age: [] - lastmodified: "2022-08-25T14:39:59Z" - mac: ENC[AES256_GCM,data:3Z1f1DobOU1RHT25TM0FI9fUUtZxrFhKeGTmXaxC+vDE2j9url28XVDesiMmj2Vairapk5krf31hV47K62Q+YvVyYrNw0a3hn+v7/2kBrbdU1SqZNajVwb7/3F5YKYNcsF/tHLClJrwYOIrSWBWsky7gim2ohItm6eKuG9ED+wg=,iv:zqMw8Q4c3EOI9AEUjx148/X2VTF1UMTdacgjxyYuiyk=,tag:H72VN77/SzHMBqys8ZONGw==,type:str] + lastmodified: "2023-04-01T22:52:16Z" + mac: ENC[AES256_GCM,data:mz8qIWirNUomuUPR9elZZK2mTfQhMqParnraw9gSQNDkhFPBCtkORys4tA9+q1stL1Edzuh6CPFzkywct64ZrKsApMdNMIqcXBc//uuF354T3B6+LmHvmMmxlQFz3hIo3Xo01sgAJinoZrIsktA0xIYV1SeBndzsmWPCtdBk/Go=,iv:hNNBxDwoppfC6kRi5kWYILdEBRjzhdeit6xRmxD+ACU=,tag:qli2XWAjf7LgbiA/nxyQGw==,type:str] pgp: - created_at: "2021-04-06T11:27:21Z" enc: | diff --git a/machines/fuuko/services/router.nix b/machines/fuuko/services/router.nix new file mode 100644 index 0000000..5b1b6d9 --- /dev/null +++ b/machines/fuuko/services/router.nix @@ -0,0 +1,215 @@ +# Home network configuration +# +# +----------+ +---------------+ +# | | | +-+-+---+ | +# | +|-|-|-|-|+ | | +# +---+----+ |5 4 3 2 1| | +--+--+ +# |upstream| |TL-SG105 | | |fuuko| +# +--------+ +---------+ | +-----+ +# | +# ( clients ) +# +# It consists of fuuko as a router (this configuration), +# connected to a TP-LINK TL-SG105E “smart managed” (i.e., it can do VLANs) 5-port switch. +# The upstream comes from some plasic Huawei router/AP I don’t control. +# +# The VLANs are configured as follows: +# Port | VLAN | ID(s) +# 5 | untagged | 2 +# 4 | tagged | 2,3 +# 1-3 | untagged | 3 +# +# Wireless currently still is done by a separate GL.iNet GL-MT300N-V2 running OpenWRT, +# but this will be changed to a Intel Wireless-AC 9260 in fuuko at a later date. +{ config, lib, ... }: +let + domain = "home.sbruder.de"; +in +{ + sops.secrets.wg-mullvad-private-key = { + owner = config.users.users.systemd-network.name; + sopsFile = ../secrets.yaml; + }; + + boot.kernel.sysctl = { + "net.ipv4.conf.all.forwarding" = true; + }; + + networking = { + # networkd handles this + useDHCP = false; + # networkd didn’t work that well for this + nat = { + enable = true; + enableIPv6 = true; + externalInterface = "wg-mullvad"; + internalInterfaces = [ "lan" ]; + internalIPv6s = [ "fd00:80:1::/64" ]; + }; + }; + + systemd.network = { + enable = true; + netdevs = { + wan = { + netdevConfig = { + Kind = "vlan"; + Name = "wan"; + }; + vlanConfig = { + Id = 2; + }; + }; + lan = { + netdevConfig = { + Kind = "vlan"; + Name = "lan"; + }; + vlanConfig = { + Id = 3; + }; + }; + wg-mullvad = { + netdevConfig = { + Kind = "wireguard"; + Name = "wg-mullvad"; + }; + wireguardConfig = { + PrivateKeyFile = config.sops.secrets.wg-mullvad-private-key.path; + FirewallMark = 51820; + }; + wireguardPeers = lib.singleton { + wireguardPeerConfig = { + Endpoint = "146.70.117.194:51820"; + PublicKey = "ydXFN45/kROELJrF6id+uIrnS5DvTKSCkZDjfL9De2Q="; + AllowedIPs = [ "0.0.0.0/0" "::0/0" ]; + PersistentKeepalive = 25; + }; + }; + }; + }; + networks = { + physical = { + name = "enp8s0"; + vlan = [ "wan" "lan" ]; + # no autoconfiguration needed, only tagged VLAN + networkConfig = { + LinkLocalAddressing = "no"; + LLDP = "no"; + EmitLLDP = "no"; + IPv6AcceptRA = "no"; + IPv6SendRA = "no"; + }; + }; + wan = { + name = "wan"; + matchConfig = { + Type = "vlan"; + }; + networkConfig = { + # Upstream provides no IPv6 :( + # If this is not set, it waits and fails systemd-networkd-wait-online + LinkLocalAddressing = "no"; + IPv6AcceptRA = "no"; + }; + DHCP = "ipv4"; + dhcpV4Config = { + UseDNS = "no"; + }; + }; + lan = { + name = "lan"; + matchConfig = { + Type = "vlan"; + }; + domains = [ domain ]; + address = [ "10.80.1.1/24" "fd00:80:1::1/64" ]; + }; + wg-mullvad = { + name = "wg-mullvad"; + address = [ "10.66.208.88/32" "fc00:bbbb:bbbb:bb01::3:d057/128" ]; + dns = [ "10.64.0.1" ]; + routingPolicyRules = [ + { + routingPolicyRuleConfig = { + FirewallMark = 51820; + InvertRule = "yes"; + Table = 51820; + Priority = 10; + #SuppressPrefixLength = 0; # can’t be used here (forwarding does not work with it) + }; + } + # FIXME: those two shouldn’t be necessary + # It should automatically detect those routes existing and prioritise them + { + routingPolicyRuleConfig = { + To = "10.80.0.0/24"; + Priority = 9; + }; + } + { + routingPolicyRuleConfig = { + To = "10.80.1.0/24"; + Priority = 9; + }; + } + ]; + routes = [ + { + routeConfig = { + Gateway = "0.0.0.0"; # point-to-point connection + Table = 51820; + }; + } + { + routeConfig = { + Gateway = "::"; + }; + } + ]; + }; + }; + }; + services.resolved.enable = false; + + services.dnsmasq = { + enable = true; + + extraConfig = '' + bogus-priv # do not forward revese lookups of internal addresses + domain-needed # do not forward names without domain + interface=lan # only respond to queries from lan + no-hosts # do not resolve hosts from /etc/hosts + no-resolv # only use explicitly configured resolvers + + cache-size=10000 + + domain=${domain} + # Allow resolving the router + interface-name=${config.networking.hostName}.${domain},lan + interface-name=${config.networking.hostName},lan + + # DHCPv4 + dhcp-range=10.80.1.20,10.80.1.150,12h + dhcp-option=option:router,10.80.1.1 + + # SLAAC (for addresses) / DHCPv6 (for DNS) + dhcp-range=fd00:80:1::,ra-stateless,ra-names + dhcp-option=option6:dns-server,fd00:80:1::1 + ''; + servers = [ + "10.64.0.1" # mullvad DNS, should be fastest overall + #"9.9.9.9" # dns.quad9.net + #"2620:fe::fe" + ]; + }; + + services.prometheus.exporters.dnsmasq = { + enable = true; + listenAddress = config.sbruder.wireguard.home.address; + leasesPath = "/var/lib/dnsmasq/dnsmasq.leases"; + }; + + networking.firewall.allowedUDPPorts = [ 53 67 ]; + networking.firewall.allowedTCPPorts = [ 53 ]; +} diff --git a/machines/renge/services/prometheus.nix b/machines/renge/services/prometheus.nix index 1338166..0e9700f 100644 --- a/machines/renge/services/prometheus.nix +++ b/machines/renge/services/prometheus.nix @@ -94,6 +94,14 @@ in }; } ) + { + job_name = "dnsmasq"; + static_configs = mkStaticTarget "fuuko.vpn.sbruder.de:${toString config.services.prometheus.exporters.dnsmasq.port}"; + relabel_configs = lib.singleton { + target_label = "instance"; + replacement = "fuuko.home.sbruder.de"; + }; + } { job_name = "hcloud"; static_configs = mkStaticTarget config.services.hcloud_exporter.listenAddress;