commit e944cd0130920993e257a64e20ab1106bfa7a293
parent 0f8cb14e3494f7fecb7c4eec54efe4dd29ea6d98
Author: Leah (ctucx) <git@ctu.cx>
Date: Fri, 28 Jun 2024 12:57:20 +0200
parent 0f8cb14e3494f7fecb7c4eec54efe4dd29ea6d98
Author: Leah (ctucx) <git@ctu.cx>
Date: Fri, 28 Jun 2024 12:57:20 +0200
machines/briefkasten: act as router
13 files changed, 425 insertions(+), 102 deletions(-)
M
|
98
++++++++-----------------------------------------------------------------------
A
|
117
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
|
88
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
|
151
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/machines/briefkasten/default.nix b/machines/briefkasten/default.nix @@ -21,30 +21,22 @@ ./scanner-sftp.nix + ./router + ./websites ]; - dns.zones."ctu.cx".subdomains."${config.networking.hostName}.home" = lib.mkIf config.networking.usePBBUplink (pkgs.dns.lib.combinators.host config.networking.primaryIP4 config.networking.primaryIP); - dns.zones."ctu.cx".subdomains."${config.networking.hostName}".CNAME = lib.mkIf config.networking.usePBBUplink [ "${config.networking.hostName}.home" ]; - dns.zones."ctu.cx".subdomains."home".CNAME = lib.mkIf config.networking.usePBBUplink [ "${config.networking.hostName}.home" ]; + # dns.zones."ctu.cx".subdomains."${config.networking.hostName}.home" = (pkgs.dns.lib.combinators.host config.networking.primaryIP4 config.networking.primaryIP); + # dns.zones."ctu.cx".subdomains."${config.networking.hostName}".CNAME = [ "${config.networking.hostName}.home" ]; + # dns.zones."ctu.cx".subdomains."home".CNAME = [ "${config.networking.hostName}.home" ]; age.secrets = { restic-server-briefkasten.file = ../../secrets/restic-server/briefkasten.age; restic-server-wanderduene.file = ../../secrets/restic-server/wanderduene.age; - - wireguard-privkey.file = ./. + "/../../secrets/${config.networking.hostName}/wireguard-privkey.age"; }; boot = { - kernel.sysctl = { - "net.ipv6.conf.all.forwarding" = true; - "net.ipv4.conf.all.forwarding" = true; - "net.ipv6.conf.enp1s0.forwarding" = lib.mkIf config.networking.usePBBUplink 0; - "net.ipv6.conf.enp1s0.autoconf" = lib.mkIf config.networking.usePBBUplink 0; - "net.ipv6.conf.enp1s0.accept_ra" = lib.mkIf config.networking.usePBBUplink 0; - }; - kernelModules = [ "intel_rapl_common" ]; # seems to make realtek ethernet faster? @@ -78,11 +70,11 @@ ip addr add ${config.networking.primaryIP4}/28 dev enp1s0 ip addr add ${config.networking.secondaryIP4}/8 dev enp1s0 - ip route add default via 195.39.246.41 dev enp1s0 onlink +# ip route add default via 195.39.246.41 dev enp1s0 onlink '' + lib.optionalString config.networking.usePBBUplink '' ip addr add ${config.networking.primaryIP}/128 dev enp1s0 - ip route add default via 2a0f:4ac0:acab::1 dev enp1s0 onlink +# ip route add default via 2a0f:4ac0:acab::1 dev enp1s0 onlink ''; }; @@ -113,81 +105,11 @@ useNetworkd = true; usePBBUplink = true; - primaryIP = "2a0f:4ac0:acab::45"; - primaryIP4 = "195.39.246.45"; - secondaryIP4 = "10.0.0.45"; + primaryIP = "2a0f:4ac0:acab::1"; + primaryIP4 = "195.39.246.42"; + secondaryIP4 = "10.0.0.1"; domain = "home.ctu.cx"; - - nameservers = [ "195.39.246.41" "2a0f:4ac0:acab::1" ]; - - defaultGateway.address = "195.39.246.41"; - defaultGateway.interface = "enp1s0"; - - defaultGateway6 = lib.mkIf config.networking.usePBBUplink{ - address = "2a0f:4ac0:acab::1"; - interface = "enp1s0"; - }; - - vlans.vlan10 = { - id = 10; - interface = "enp1s0"; - }; - - bridges.bruplink = { - interfaces = [ "vlan10" "iphone" ]; - }; - - interfaces.enp1s0 = { - ipv4.addresses = [ - (lib.mkIf config.networking.usePBBUplink { - address = config.networking.primaryIP4; - prefixLength = 28; - }) - { - address = config.networking.secondaryIP4; - prefixLength = 8; - } - ]; - - ipv6.addresses = lib.mkIf config.networking.usePBBUplink [{ - address = config.networking.primaryIP; - prefixLength = 62; - }]; - }; - - wireguard = { - enable = true; - - interfaces.wg-wanderduene = { - listenPort = 51820; - privateKeyFile = config.age.secrets.wireguard-privkey.path; - generatePrivateKeyFile = true; - postSetup = "ip link set dev wg-wanderduene mtu 1500"; - ips = [ "172.17.0.2/24" ]; - - peers = [ - { - persistentKeepalive = 10; - endpoint = "46.38.253.139:51821"; - allowedIPs = [ "172.17.0.0/24" ]; - publicKey = "hOUeP8RFchzJXyy8DceTFKN9f1VHi9GzZQii0dX2zww="; - } - ]; - }; - }; - - firewall.allowedTCPPorts = [ 5201 ]; - firewall.allowedUDPPorts = [ 5201 51820 ]; - firewall.trustedInterfaces = [ "wg-wanderduene" "vlan10" "bruplink" ]; - firewall.extraCommands = '' - iptables -A nixos-fw -p tcp -s 10.0.0.0/8 -j nixos-fw-accept - iptables -A nixos-fw -p udp -s 10.0.0.0/8 -j nixos-fw-accept - iptables -A nixos-fw -p tcp -s 195.39.246.32/28 -j nixos-fw-accept - iptables -A nixos-fw -p udp -s 195.39.246.32/28 -j nixos-fw-accept - ip6tables -A nixos-fw -p tcp -s 2a0f:4ac0:acab::/48 -j nixos-fw-accept - ip6tables -A nixos-fw -p udp -s 2a0f:4ac0:acab::/48 -j nixos-fw-accept - ''; }; services = {
diff --git a/machines/briefkasten/gotosocial.nix b/machines/briefkasten/gotosocial.nix @@ -5,7 +5,8 @@ let in { - dns.zones."ctu.cx".subdomains."fedi.home".CNAME = lib.mkIf config.networking.usePBBUplink [ "${config.networking.fqdn}." ]; +# dns.zones."ctu.cx".subdomains."fedi.home".CNAME = [ "${config.networking.fqdn}." ]; + services.dnsmasq.settings.cname = [ "fedi.home.ctu.cx, ${config.networking.fqdn}" ]; age.secrets.restic-gotosocial.file = ./. + "/../../secrets/${config.networking.hostName}/restic/gotosocial.age"; age.secrets.gotosocial-env.file = ./. + "/../../secrets/${config.networking.hostName}/gotosocial-env.age";
diff --git a/machines/briefkasten/router/default.nix b/machines/briefkasten/router/default.nix @@ -0,0 +1,23 @@ +{ pkgs, ... }: + +{ + + imports = [ + ./systemd-networkd.nix + ./nftables.nix + ./dnsmasq.nix + ]; + + boot = { + kernel.sysctl."net.ipv4.ip_forward" = true; + kernel.sysctl."net.ipv6.conf.all.forwarding" = true; + }; + + environment.systemPackages = with pkgs; [ + wireguard-tools + ]; + + services.avahi.interfaces = [ "brlan" ]; + networking.useDHCP = false; + +}
diff --git a/machines/briefkasten/router/dnsmasq.nix b/machines/briefkasten/router/dnsmasq.nix @@ -0,0 +1,117 @@ +{ config, pkgs, ... }: + +{ + + dns.zones."ctu.cx".subdomains = with pkgs.dns.lib.combinators; { + home.NS = [ "home.ctu.cx." ]; + home.A = [ (a "195.39.246.42") ]; + home.AAAA = [ "2a0f:4ac0:acab::1" ]; + }; + + systemd.services.dnsmasq.onFailure = [ "email-notify@%i.service" ]; + + services = { + + resolved.enable = false; + + dnsmasq = { + enable = true; + settings = { + local-service = true; + no-resolv = true; + no-hosts = true; + domain-needed = true; + bogus-priv = true; + + enable-ra = true; + quiet-ra = true; + + server = [ "1.1.1.1" "1.0.0.1" "8.8.8.8" "8.8.4.4" ]; + + local = "/home.ctu.cx/"; + domain = "home.ctu.cx"; + + auth-ttl = 600; + auth-server = "home.ctu.cx, 195.39.246.42, 2a0f:4ac0:acab::1"; + auth-zone = "home.ctu.cx, 10.0.0.1/24, 195.39.246.32/28, 2a0f:4ac0:acab::1/64"; + + host-record = [ + "home.ctu.cx, 195.39.246.42, 2a0f:4ac0:acab::1" + ]; + + cname = [ + "briefkasten.home.ctu.cx, home.ctu.cx" + "dnsmasq.home.ctu.cx, home.ctu.cx" + ]; + + address = [ + "/briefkasten/10.0.0.1" + "/ads1700w/10.0.0.10" + "/scanner/10.0.0.10" + ]; + + dhcp-authoritative = true; + dhcp-rapid-commit = true; + dhcp-sequential-ip = true; + + dhcp-range = [ + "private, 10.0.0.100, 10.0.0.200, 255.255.255.0, 48h" + "public, 195.39.246.34, static, 255.255.255.240, 195.39.246.47, 48h" + " 2a0f:4ac0:acab::100, 2a0f:4ac0:acab::01ff, ra-names,slaac, 64, 48h" + ]; + + dhcp-option = [ + "option6:information-refresh-time, 6h" + "option6:dns-server, [2a0f:4ac0:acab::1]" + + "private, option:router, 10.0.0.1" + "private, option:dns-server, 10.0.0.1" + + "public, option:router, 195.39.246.42" + "public, option:dns-server, 195.39.246.42" + ]; + + + dhcp-host = [ + "48:a9:8a:8e:dd:0b, accesspoint, 10.0.0.2" + "5c:f3:70:b9:35:9c, ctux-ads1700w, 10.0.0.10" + "34:31:c4:46:88:31, pbx, 10.0.0.20" + + "id:bc:6e:e2:03:99:40, nadia-work, [2a0f:4ac0:acab::37]" + "bc:6e:e2:03:99:40, nadia-work, 195.39.246.37" + + "id:1c:57:dc:40:dc:b2, blechkasten, [2a0f:4ac0:acab::43]" + "1c:57:dc:40:dc:b2, blechkasten, 195.39.246.43" + + "id:00:e0:4c:02:13:75, desktop, [2a0f:4ac0:acab::44]" + "00:e0:4c:02:13:75, desktop, 195.39.246.44" + + "id:f4:3b:d8:cb:7c:49, coladose, [2a0f:4ac0:acab::45]" + "f4:3b:d8:cb:7c:49, coladose, 195.39.246.45" + ]; + }; + }; + + fcgiwrap.enable = true; + + nginx = { + enable = true; + virtualHosts."dnsmasq.home.ctu.cx" = { + enableACME = true; + forceSSL = true; + kTLS = true; + locations = { + "/".extraConfig = '' + include "${pkgs.nginx}/conf/fastcgi_params"; + fastcgi_param SCRIPT_FILENAME "${pkgs.dnsmasq-lease-overview}/bin/overview"; + fastcgi_param LEASE_PATH "/var/lib/dnsmasq/dnsmasq.leases"; + fastcgi_param QUERY_STRING $args; + fastcgi_pass unix:${config.services.fcgiwrap.socketAddress}; + ''; + }; + }; + }; + + }; + +}
diff --git a/machines/briefkasten/router/nftables.nix b/machines/briefkasten/router/nftables.nix @@ -0,0 +1,14 @@ +{ ... }: + +{ + + networking = { + firewall.enable = false; + + nftables = { + enable = true; + rulesetFile = ./ruleset.nft; + }; + }; + +}+ \ No newline at end of file
diff --git a/machines/briefkasten/router/ruleset.nft b/machines/briefkasten/router/ruleset.nft @@ -0,0 +1,87 @@ +flush ruleset + +table inet firewall { + chain inbound { + # By default, drop all traffic unless it meets a filter + # criteria specified by the rules that follow below. + type filter hook input priority 0; + policy drop; + + # Allow traffic from established and related packets. + ct state established,related accept + + # Drop invalid packets. + ct state invalid drop + + # Allow local connections. + iifname lo accept + iifname brlan accept + + # Allow all ICMP and IGMP traffic, but enforce a rate limit + # to help prevent some types of flood attacks. + ip protocol icmp limit rate 5/second accept + ip protocol igmp limit rate 5/second accept + #ip6 protocol ipv6-icmp icmpv6-type redirect drop + #ip6 protocol ipv6-icmp icmpv6-type 139 drop + ip6 nexthdr ipv6-icmp limit rate 5/second accept + + # Allow some ports + tcp dport ssh accept comment "ssh" + tcp dport domain accept comment "dns (tcp)" + udp dport domain accept comment "dns (udp)" + tcp dport http accept comment "http" + tcp dport https accept comment "https" + tcp dport 22000 accept comment "syncthing" + udp dport 21027 accept comment "syncthing" + tcp dport 5201 accept comment "iperf3 (tcp)" + udp dport 5201 accept comment "iperf3 (udp)" + } + + chain forward { + # By default, drop all traffic unless it meets a filter + type filter hook forward priority 0; + policy drop; + + # Allow traffic from established and related packets. + ct state established,related accept + + # Drop invalid packets. + ct state invalid drop + + # local clients can do whatever + iifname brlan accept + + # Allow all ICMP and IGMP traffic, but enforce a rate limit + # to help prevent some types of flood attacks. + ip protocol icmp limit rate 5/second accept + ip6 nexthdr ipv6-icmp limit rate 5/second accept + ip protocol igmp limit rate 5/second accept + + # drop incomming netbios traffic + tcp dport {139, 445} counter drop comment "silently drop NetBios" + udp dport {137, 138} counter drop comment "silently drop NetBios" + + #make public ips world accessible + ip daddr 195.39.246.33/28 accept + } + + chain outbound { + # Allow all outbound traffic + type filter hook output priority 0 + policy accept + } + +} + +table ip nat { + chain prerouting { + type nat hook prerouting priority -100 + policy accept + } + + chain postrouting { + type nat hook postrouting priority 0 + policy accept + oifname iphone masquerade + } +}+ \ No newline at end of file
diff --git a/machines/briefkasten/router/systemd-networkd.nix b/machines/briefkasten/router/systemd-networkd.nix @@ -0,0 +1,150 @@ +{ config, ... }: + +{ + + age.secrets.wireguard-privkey = { + file = ./. + "../../../../secrets/${config.networking.hostName}/wireguard-privkey.age"; + mode = "640"; + owner = "root"; + group = "systemd-network"; + }; + + systemd.network = { + enable = true; + wait-online.enable = false; + + links = { + "10-iphone" = { + matchConfig.PermanentMACAddress = "aa:ab:b5:18:95:d9"; + linkConfig.Name = "iphone"; + }; + }; + + netdevs = { + + "20-brlan" = { + netdevConfig = { + Kind = "bridge"; + Name = "brlan"; + }; + }; + + # "30-enp1s0.5" = { + # netdevConfig = { + # Kind = "vlan"; + # Name = "enp1s0.5"; + # }; + # vlanConfig = { + # Id = 5; + # }; + # }; + + "40-wg-pbb" = { + netdevConfig = { + Kind = "wireguard"; + Name = "wg-pbb"; + }; + wireguardConfig = { + PrivateKeyFile = config.age.secrets.wireguard-privkey.path; + ListenPort = 51820; + FirewallMark = 51820; + }; + wireguardPeers = [{ + wireguardPeerConfig={ + Endpoint = "195.39.247.161:51820"; + PublicKey = "kih/GnR4Bov/DM/7Rd21wK+PFQRUNH6sywVuNKkUAkk="; + AllowedIPs = [ "0.0.0.0/0" "::/0" ]; + PersistentKeepalive = 10; +# RouteTable = "off"; + }; + }]; + }; + + }; + + networks = { + + "10-iphone" = { + matchConfig = { + Name = "iphone"; + }; + DHCP = "yes"; + }; + + # "10-enp1s0.5" = { + # matchConfig = { + # Name = "enp1s0.5"; + # }; + # DHCP = "yes"; + # }; + + "10-enp1s0" = { + matchConfig = { + Name = "enp1s0"; + }; + bridge = [ "brlan" ]; +# vlan = [ "enp1s0.5" ]; + }; + + "20-brlan" = { + matchConfig = { + Name = "brlan"; + Driver = "bridge"; + }; + networkConfig = { + IPv6AcceptRA = "no"; + DHCP = "no"; + }; + address = [ + "10.0.0.1/24" + "195.39.246.42/28" + "2a0f:4ac0:acab::1/62" + ]; + routingPolicyRules = [ + { routingPolicyRuleConfig = { + From = "195.39.246.32/28"; + Table = 254; + Priority = 1900; + SuppressPrefixLength = 0; + };} + { routingPolicyRuleConfig = { + From = "2a0f:4ac0:acab::/62"; + Table = 254; + Priority = 1900; + SuppressPrefixLength = 0; + };} + { routingPolicyRuleConfig = { + From = "195.39.246.32/28"; + Table = 1234; + Priority = 2000; + };} + { routingPolicyRuleConfig = { + From = "2a0f:4ac0:acab::/62"; + Table = 1234; + Priority = 2000; + };} + ]; + }; + + "30-wg-pbb" = { + matchConfig = { + Name = "wg-pbb"; + }; + linkConfig = { + MTUBytes = "1500"; + }; + routes = [ + { routeConfig = { + Destination = "0.0.0.0/0"; + Table = "1234"; + };} + { routeConfig = { + Destination = "::/0"; + Table = "1234"; + };} + ]; + }; + + }; + }; +}+ \ No newline at end of file
diff --git a/machines/briefkasten/smarthome/influxdb2.nix b/machines/briefkasten/smarthome/influxdb2.nix @@ -5,7 +5,8 @@ age.secrets.restic-influxdb.file = ./. + "/../../../secrets/${config.networking.hostName}/restic/influxdb.age"; age.secrets.influx-backup-env.file = ./. + "/../../../secrets/${config.networking.hostName}/influx/backup_env.age"; - dns.zones."ctu.cx".subdomains."influx.home".CNAME = lib.mkIf config.networking.usePBBUplink [ "${config.networking.fqdn}." ]; +# dns.zones."ctu.cx".subdomains."influx.home".CNAME = [ "${config.networking.fqdn}." ]; + services.dnsmasq.settings.cname = [ "influx.home.ctu.cx, ${config.networking.fqdn}" ]; systemd.services.restic-backup-influxdb.serviceConfig.EnvironmentFile = config.age.secrets.influx-backup-env.path;
diff --git a/machines/briefkasten/smarthome/mqtt-webui/default.nix b/machines/briefkasten/smarthome/mqtt-webui/default.nix @@ -6,7 +6,8 @@ let in { - dns.zones."ctu.cx".subdomains."smart.home".CNAME = lib.mkIf config.networking.usePBBUplink [ "${config.networking.fqdn}." ]; +# dns.zones."ctu.cx".subdomains."smart.home".CNAME = [ "${config.networking.fqdn}." ]; + services.dnsmasq.settings.cname = [ "smart.home.ctu.cx, ${config.networking.fqdn}" ]; services = {
diff --git a/machines/briefkasten/websites/audiobooks.home.ctu.cx.nix b/machines/briefkasten/websites/audiobooks.home.ctu.cx.nix @@ -2,7 +2,8 @@ { - dns.zones."ctu.cx".subdomains."audiobooks.home".CNAME = lib.mkIf config.networking.usePBBUplink [ "${config.networking.fqdn}." ]; +# dns.zones."ctu.cx".subdomains."audiobooks.home".CNAME = [ "${config.networking.fqdn}." ]; + services.dnsmasq.settings.cname = [ "audiobooks.home.ctu.cx, ${config.networking.fqdn}" ]; fileSystems."/mnt/audiobooks" = { device = "/nix/persist/home/leah/syncthing/Audiobooks";
diff --git a/machines/briefkasten/websites/music.home.ctu.cx.nix b/machines/briefkasten/websites/music.home.ctu.cx.nix @@ -9,7 +9,8 @@ let in { - dns.zones."ctu.cx".subdomains."music.home".CNAME = lib.mkIf config.networking.usePBBUplink [ "${config.networking.fqdn}." ]; +# dns.zones."ctu.cx".subdomains."music.home".CNAME = [ "${config.networking.fqdn}." ]; + services.dnsmasq.settings.cname = [ "music.home.ctu.cx, ${config.networking.fqdn}" ]; fileSystems."/mnt/music_originals" = { device = "/nix/persist/home/leah/syncthing/Music (Originals)";
diff --git a/machines/briefkasten/websites/wiki.home.ctu.cx.nix b/machines/briefkasten/websites/wiki.home.ctu.cx.nix @@ -2,7 +2,8 @@ { - dns.zones."ctu.cx".subdomains."wiki.home".CNAME = lib.mkIf config.networking.usePBBUplink [ "${config.networking.fqdn}." ]; +# dns.zones."ctu.cx".subdomains."wiki.home".CNAME = [ "${config.networking.fqdn}." ]; + services.dnsmasq.settings.cname = [ "wiki.home.ctu.cx, ${config.networking.fqdn}" ]; fileSystems."/mnt/wiki" = { device = "/nix/persist/home/leah/syncthing/Wiki";
diff --git a/secrets/briefkasten/wireguard-privkey.age b/secrets/briefkasten/wireguard-privkey.age @@ -1,10 +1,11 @@ -----BEGIN AGE ENCRYPTED FILE----- -YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnQk1jbTlsaCtSaE1BU21s -UlRTRHUyaFpQbFhDN1Q4MlVGMWxYOUJCZXgwCjRtZjlXRTBpblpLeHc5bi9DMThl -ZmxseklHc3VGZnltWnlhN0hxelZCTTgKLT4gc3NoLWVkMjU1MTkgNGhLQ013IGpH -bXNCR0hoNU9nQ0IxZDNvNldkRTNCOFJEaitaVUxBRi9OUURqMmlGRDgKNFBkWHZ6 -OUJtMUlrOUpGL280Vmk4MVVZOHlSZ3d1ejJqVmluQi9FbjlMRQotPiB2ZS1ncmVh -c2UgLS9QCmFVWGkwWjZCCi0tLSAyNWZtQnJ3aDlnbXFwbGwvT2FLN2VHNWVjOTZ6 -eGJHWDVsQmluUndKVlVrCuTFDs+3riA4XGKIxseSSIGgClejnpBMSWr9cKEBlQTh -J8SqmwY1AysWI4fLpvtpLvbljjpLb9eHW+et5adopPnHKchVpM8TM8VcHEDM +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwamJHZDJIbVM2OEJUM1Bo +V2VTRnU1T0NIamdFWVQzVlRMZG1mSFU3cFF3CmlVR2M1dnM5eEVsV3NwOVR4N2lZ +dXpVajZ5Z2xYNDNZRDMwMDY4WnhHSVUKLT4gc3NoLWVkMjU1MTkgNGhLQ013IFRL +ZUxmUW5VQ0Jhd3A2dk10UkVUVG1USERlS0lCeU9XQkh0T050VXpURDQKVllaTkhB +K2VHblYzYjlXOXJVUStvQnRKeTNWU3NMTXVGT2dwUEZuQy95OAotPiBwLWdyZWFz +ZSAiNzxidSAoOiVSCjFiQkI3bTc0c3FZCi0tLSBDVmowUEt3RDlENlB1V2NkaWMv +NVZ5akVYSTVCMGVDbWdtZFE5NDd2dDRRCtdDEf/ug4fzXOZwPrf6zmKRfpG4tFi9 +YT610Z0H/DMjoqwD/WdLid4MXG61bShM/I/zJHjq4M2/q0HUL7Mg/qEVs2adBfl5 +4dglMFw= -----END AGE ENCRYPTED FILE-----