diff --git a/flake.nix b/flake.nix index d649991f..782b7de5 100644 --- a/flake.nix +++ b/flake.nix @@ -130,7 +130,6 @@ #darwinModules = lib.my.mapModulesRec ./darwin-modules import; nixosConfigurations = processConfigurations { picard = nixosSystem "x86-64-linux" [ ./hosts/picard/default.nix ]; # TODO - wormhole = nixosSystem "aarch64-linux" [ ./hosts/wormhole/default.nix ]; # TODO ds9 = nixosSystem "x86-64-linux" [ ./hosts/ds9/default.nix ]; # TODO }; darwinConfigurations = processConfigurations { diff --git a/hosts/wormhole/default.nix b/hosts/wormhole/default.nix deleted file mode 100644 index dfe81302..00000000 --- a/hosts/wormhole/default.nix +++ /dev/null @@ -1,92 +0,0 @@ -{ config, inputs, pkgs, lib, ... }: -{ - imports = [ - "${inputs.nixpkgs}/nixos/modules/installer/sd-card/sd-image-aarch64.nix" - "${inputs.nixos-hardware}/raspberry-pi/4/default.nix" - ./router.nix - ]; - nixpkgs.overlays = [ - (final: super: { - makeModulesClosure = x: - super.makeModulesClosure (x // { allowMissing = true; }); - }) - ]; - boot.loader.systemd-boot.enable = false; - boot.kernelPackages = pkgs.linuxPackages_rpi4; - boot.supportedFilesystems = lib.mkForce [ "reiserfs" "vfat" "zfs" "ext4" ]; # we dont need zfs here - boot.inird.supportedFilesystems = lib.mkForce [ "reiserfs" "vfat" "zfs" "ext4" ]; # we dont need zfs here - networking.hostId = "eec43f51"; - # networking.usePredictableInterfaceNames = false; - documentation.enable = false; - documentation.nixos.enable = false; - - nix = { - autoOptimiseStore = true; - gc = { - automatic = true; - dates = "weekly"; - options = "--delete-older-than 30d"; - }; - # Free up to 1GiB whenever there is less than 100MiB left. - extraOptions = '' - min-free = ${toString (100 * 1024 * 1024)} - max-free = ${toString (1024 * 1024 * 1024)} - ''; - }; - powerManagement.cpuFreqGovernor = "ondemand"; - - # Assuming this is installed on top of the disk image. - fileSystems = { - "/" = { - device = "/dev/disk/by-label/NIXOS_SD"; - fsType = "ext4"; - options = [ "noatime" ]; - }; - }; - - ragon.networking.router.enable = true; - ragon.services.ssh.enable = true; - ragon.cli.enable = true; - ragon.cli.maximal = false; - services.lorri.enable = false; - ragon.services.ddns.enable = true; - ragon.services.tailscale.enable = true; - ragon.services.nginx.enable = true; - services.nginx.virtualHosts."h.hailsatan.eu" = { - forceSSL = true; - useACMEHost = "hailsatan.eu"; - extraConfig = '' - proxy_buffering off; - ''; - locations."/".proxyPass = "http://10.0.0.20:8123"; - locations."/".proxyWebsockets = true; - }; - services.nginx.virtualHosts."hailsatan.eu" = { - forceSSL = true; - useACMEHost = "hailsatan.eu"; - root = pkgs.runCommand "homepage" { } '' - mkdir -p $out - echo "Hail Satan" > $out/index.html - echo "User-agent: *" > $out/robots.txt - echo "Disallow: /" >> $out/robots.txt - ''; - }; - services.nginx.virtualHosts."j.hailsatan.eu" = { - forceSSL = true; - useACMEHost = "hailsatan.eu"; - extraConfig = '' - proxy_buffering off; - ''; - locations."/".proxyPass = "https://j.hailsatan.eu"; - locations."/".proxyWebsockets = true; - }; - - users.users.root.openssh.autorizedKeys = [ - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDiKJEYNUU+ZpbOyJf9k9ZZdTTL0qLiZ6fXEBVCjNfas" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIkFgHr6OMwsnGhdG4TwKdthlJC/B9ELqZfrmJ9Sf7qk" - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCJVa1zAjR6stS4qIEysQbR9n0/AV2h62QRfsRvNfQiL19ExKFR7ZHaUFBr6jnGjzl5eyK0DtwZMlyaDlTR/AXiTZHJrvEPL1lna42wK252uZb66DXAG23L+iFeXySq3f+a6Prw8NU3HvIvC/YkEYwjjbqPKEjvnIHd2dJ1FZ9T9FeoKup3nMWYGDRqrja8NcRwCY9OpPd3ZKZJlNJcPfbfAipGAuQ6EGgGi0GzqoYP9OqZx9PBQQEY7a5+cUgYYEI75NJNuk4/WBm8fkFKrcOmvhTOEb90kbNmpHusDOrFEo8LATdpmJSG013DpPb1W7pMxMq+YgFF4INqIxrhBGht" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH8RjUQ6DDDDgsVbqq+6zz1q6cBkus/BLUGa9JoWsqB4" - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCWwrrROqkBEZi8t7Czu1jDDJjSqomGXx7dhIx73GTb3bBlgThqUSsrG+NpP9mxNl4sYgmJYQ9idpUW/RTX3/sXBvNQi4rOqv9z1qdEyzF86CcyWGk4f+D2hJffLlcIbvbDCJ92PF+k5NbH+PC/yVZKSIRC3ENBHf38l8n25ABuBcpCI16bPCIbqbpekqStXClug//uAyENuS6+orHFQg3muUihEedEhJly1QAfDhOzZRlBxTGQcDvZA/XMaIyjAqbXaNVRsDLmKezm/Dg5M3jMIRxApUd9hcuZlfemxUgD0qqnJSTahb9rMxUKk5jdY95EthAp0s2e6tc2O76sYPqb" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH99QITZa3hSa+7sMo4M5IC5mXWEjsRqXUSaYKKRyQfE" - ]; -} diff --git a/hosts/wormhole/router.nix b/hosts/wormhole/router.nix deleted file mode 100644 index 77c88620..00000000 --- a/hosts/wormhole/router.nix +++ /dev/null @@ -1,422 +0,0 @@ -{ config, lib, pkgs, ... }: -with lib; -with lib.my; -let - wgEnabled = hasAttrByPath [ "hosts" config.networking.hostName ] (importTOML ../../data/wireguard.toml); - cfg = config.ragon.networking.router; - waninterface = cfg.waninterface; - laninterface = cfg.laninterface; - prefixSize = cfg.prefixSize; - statics = cfg.statics; - domain = cfg.domain; - disableFirewallFor = cfg.disableFirewallFor; - lan = { - name = "lan"; - internet = true; - allowipv6 = true; - ipv4addr = "10.0.0.1"; - netipv4addr = "10.0.0.0"; - dhcpv4start = "10.0.10.1"; - dhcpv4end = "10.0.255.240"; - routes = [ - { address = "10.12.0.0"; prefixLength = 16; via = "10.0.1.2"; } - { address = "10.13.0.0"; prefixLength = 16; via = "10.0.1.2"; } - ]; - ipv4size = 16; - vlan = 4; - }; - iot = { - name = "iot"; - internet = false; - allowipv6 = false; - ipv4addr = "10.1.0.1"; - netipv4addr = "10.1.0.0"; - dhcpv4start = "10.1.1.1"; - dhcpv4end = "10.1.255.240"; - routes = [ ]; - ipv4size = 16; - vlan = 2; - }; - guest = { - name = "guest"; - internet = true; - allowipv6 = false; - ipv4addr = "192.168.2.1"; - netipv4addr = "192.168.2.0"; - dhcpv4start = "192.168.2.10"; - dhcpv4end = "192.168.2.240"; - routes = [ ]; - ipv4size = 24; - vlan = 3; - }; - nets = [ lan iot guest ]; - ipv6nets = builtins.filter (a: a.allowipv6) nets; - interfaceGenerator = obj: { - "${obj.name}".ipv4 = { - addresses = [{ - address = obj.ipv4addr; - prefixLength = obj.ipv4size; - }]; - routes = [{ - address = obj.netipv4addr; - prefixLength = obj.ipv4size; - }] ++ obj.routes; - }; - }; -in -{ - options.ragon.networking.router.enable = mkBoolOpt false; - options.ragon.networking.router.waninterface = - lib.mkOption { - type = lib.types.str; - default = "eth1"; - }; - options.ragon.networking.router.laninterface = - lib.mkOption { - type = lib.types.str; - default = "eth0"; - }; - options.ragon.networking.router.domain = - lib.mkOption { - type = lib.types.str; - default = "hailsatan.eu"; - }; - options.ragon.networking.router.prefixSize = - lib.mkOption { - type = lib.types.int; - default = 59; - }; - options.ragon.networking.router.statics = - lib.mkOption { - type = lib.types.listOf lib.types.attrs; - default = [ - { name = "j.hailsatan.eu"; ip = "10.0.0.2"; } - { name = "paperless.hailsatan.eu"; ip = "10.0.0.2"; } - { name = "unifi.hailsatan.eu"; ip = "10.0.0.2"; } - { name = "nix.hailsatan.eu"; ip = "10.0.0.2"; } - { name = "h.hailsatan.eu"; ip = "10.0.0.1"; } - { name = "grafana.hailsatan.eu"; ip = "10.0.0.2"; } - { name = "nzbr.de"; ip = "10.0.1.2"; } - { name = "storm.nzbr.de"; ip = "45.9.63.165"; } - { name = "avalanche.nzbr.de"; ip = "202.61.247.0"; } - ]; - }; - options.ragon.networking.router.disableFirewallFor = - lib.mkOption { - type = lib.types.listOf lib.types.attrs; - default = [ - { hostname = "enterprise"; mac = "d8:cb:8a:76:09:0a"; tcpports = [ 22 ]; udpports = [ ]; } - { hostname = "earthquake"; mac = "78:24:af:bc:0c:07"; tcpports = [ 22 22000 ]; udpports = [ 22000 51820 ]; } - ]; - }; - options.ragon.networking.router.staticDHCPs = - lib.mkOption { - type = lib.types.listOf lib.types.attrs; - default = [ - # ragon - machines - { name = "enterprise"; ip = "10.0.0.9"; mac = "d8:cb:8a:76:09:0a"; } - { name = "ds9"; ip = "10.0.0.2"; mac = "f4:b5:20:0e:21:d5"; } - # ragon - vms - { name = "homeassistant"; ip = "10.0.0.20"; mac = "52:54:00:a1:04:14"; } - { name = "enterprise-win"; ip = "10.0.0.201"; mac = "52:54:00:f3:ab:dd"; } - # ragon - iot - { name = "zbbridge"; ip = "10.1.0.5"; mac = "98:f4:ab:e2:b6:a3"; } - { name = "wled-Schrank-Philipp"; ip = "10.1.0.10"; mac = "2c:f4:32:20:74:60"; } - { name = "wled-Betthintergrund-Phi"; ip = "10.1.0.11"; mac = "2c:3a:e8:0e:ab:71"; } - - # nzbr - machines - { name = "earthquake"; ip = "10.0.1.2"; mac = "78:24:af:bc:0c:07"; } - { name = "comet"; ip = "10.0.1.4"; mac = "0c:98:38:d3:16:8f"; } - { name = "meteor"; ip = "10.0.1.8"; mac = "54:27:1e:5c:1f:ed"; } # Wireless - { name = "meteor"; ip = "10.0.1.16"; mac = "00:21:cc:5c:f5:dc"; } # Wired - { name = "hurricane"; ip = "10.0.1.32"; mac = "f0:2f:74:1b:af:e0"; } - - # nzbr - vms - { name = "earthquake-macos"; ip = "10.0.1.201"; mac = "52:54:00:8e:e2:66"; } - { name = "earthquake-win"; ip = "10.0.1.202"; mac = "52:54:00:97:37:69"; } - - # nzbr - consoles - { name = "xbox"; ip = "10.0.2.1"; mac = "58:82:a8:30:2d:1c"; } - { name = "wii"; ip = "10.0.2.2"; mac = "00:23:cc:50:78:00"; } - { name = "switch"; ip = "10.0.2.3"; mac = "dc:68:eb:bb:01:fc"; } # Wireless - ]; - }; - options.ragon.networking.router.forwardedPorts = - lib.mkOption { - type = lib.types.listOf lib.types.attrs; - default = [ - #{ proto = "tcp"; sourcePort = "5060-5061"; destination = "10.0.0.11"; } - ]; - }; - config = { - # https://www.willghatch.net/blog/2020/06/22/nixos-raspberry-pi-4-google-fiber-router/ - - # You’d better forward packets if you actually want a router. - boot.kernel.sysctl = { - "net.ipv4.ip_forward" = 1; - "net.ipv6.conf.all.forwarding" = 1; - "net.ipv6.conf.default.forwarding" = 1; - "net.ipv6.conf.6rdtun.forwarding" = 1; - }; - - networking.vlans = - let - genVlan = obj: { - "${obj.name}" = { - id = obj.vlan; - interface = laninterface; - }; - }; - in - lib.foldl (a: b: a // b) { } (map genVlan nets); - - networking.interfaces = - let - genVlanConf = lib.foldl (a: b: a // b) { } (map interfaceGenerator nets); - in - { - "${waninterface}" = { - useDHCP = true; - }; - } // genVlanConf; - networking.dhcpcd = { - enable = true; - allowInterfaces = [ - "${waninterface}" - ] ++ (map (a: a.name) ipv6nets); - extraConfig = - let - genDesc = obj: '' - # We don’t want dhcpcd to give us an address on the ${obj.name} interface. - interface ${obj.name} - noipv4 - - ''; - allGenIntDescs = builtins.concatStringsSep "\n" (map genDesc ipv6nets); - in - '' - # The man page says that ipv6rs should be disabled globally when - # using a prefix delegation. - noipv6rs - - interface ${waninterface} - # On the wan interface, we want to ask for a prefix delegation. - iaid 0 - ipv6rs - ia_pd 0/::/${toString prefixSize} lan/0/${toString prefixSize} - - ${allGenIntDescs} - ''; - runHook = '' - if [[ "$reason" == "BOUND6" ]] || [[ "$reason" == "REBIND6" ]]; then - ${pkgs.python3}/bin/python3 ${pkgs.writeScript "dhcpcd-runHook.py" '' - import json - import sys - import subprocess - import os - - prefix = os.environ.get("new_dhcp6_ia_pd1_prefix1")[:-1] - - # https://stackoverflow.com/a/37316533/12852285 - def mac2ipv6(mac): - # only accept MACs separated by a colon - parts = mac.split(":") - - # modify parts to match IPv6 value - parts.insert(3, "ff") - parts.insert(4, "fe") - parts[0] = "%x" % (int(parts[0], 16) ^ 2) - - # format output - ipv6Parts = [] - for i in range(0, len(parts), 2): - ipv6Parts.append("".join(parts[i:i+2])) - ipv6 = "%s%s" % (prefix, ":".join(ipv6Parts)) - return ipv6 - - data = json.loads("""${builtins.toJSON disableFirewallFor}""") - for host in data: - print('setting firewall rules for ' + host["hostname"]) - IP = mac2ipv6(host["mac"]) - if len(host["tcpports"]) > 0: - subprocess.run(["${pkgs.nftables}/bin/nft", "insert", "rule", "inet", "filter", "forward", "ip6", "daddr", IP, "tcp", "dport", f'{{ {", ".join(map(str, host["tcpports"]))} }}', "accept" ]) - if len(host["udpports"]) > 0: - subprocess.run(["${pkgs.nftables}/bin/nft", "insert", "rule", "inet", "filter", "forward", "ip6", "daddr", IP, "udp", "dport", f'{{ {", ".join(map(str, host["udpports"]))} }}', "accept" ]) - subprocess.run(["${pkgs.nftables}/bin/nft", "insert", "rule", "inet", "filter", "forward", "ip6", "daddr", IP, "icmpv6", "type", "{ destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request, echo-reply, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert }", "accept"]) - ''} - fi - ''; - }; - - networking.firewall.enable = false; # disable iptables cause it's ass to set up - networking.nftables.enable = true; - networking.nftables.ruleset = - let - unsafeInterfaces = (map (x: x.name) (filter (x: x.internet == false) nets)); - safeInterfaces = (map (x: x.name) (filter (x: x.internet == true) nets)) ++ [ "lo" ] ++ (optionals (wgEnabled) [ "wg0" ]); - allInternalInterfaces = (map (x: x.name) nets) ++ [ "lo" ]; - portForwards = concatStringsSep "\n" (map (x: "iifname ${waninterface} ${x.proto} dport ${toString x.sourcePort} dnat ${x.destination}") cfg.forwardedPorts); - dropUnsafe = concatStringsSep "\n" (map (x: "iifname ${x} drop") unsafeInterfaces); - allowSafe = concatStringsSep "\n" (map (x: "iifname ${x} accept") safeInterfaces); - allowSafeOif = concatStringsSep "\n" (map (x: "oifname ${x} ct state { established, related } accept") safeInterfaces); - allowAll = concatStringsSep "\n" (map (x: "iifname ${x} accept") (allInternalInterfaces ++ (optionals (wgEnabled) [ "wg0" ]))); - in - '' - define unsafe_interfaces = { - ${concatStringsSep ",\n" unsafeInterfaces} - } - define safe_interfaces = { - lo, - ${concatStringsSep ",\n" safeInterfaces} - } - define all_interfaces = { - lo, - ${concatStringsSep ",\n" allInternalInterfaces} - } - table inet filter { - chain input { - type filter hook input priority 0; - - # allow established/related connections - ct state { established, related } accept - - # early drop of invalid connections - ct state invalid drop - - # allow from loopback and internal nic - ${allowAll} - - # allow icmp - ip protocol icmp icmp type echo-request limit rate over 1/second burst 5 packets drop - ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate over 1/second burst 5 packets drop - ip protocol icmp icmp type { destination-unreachable, echo-reply, echo-request, source-quench, time-exceeded } accept - ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, echo-reply, echo-request, nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert, packet-too-big, parameter-problem, time-exceeded } accept - - # open port 22, but only allow 2 new connections per minute from each ip - tcp dport 22 ct state new flow table ssh-ftable { ip saddr limit rate 2/minute } accept - tcp dport 80 accept - tcp dport 443 accept - udp dport 51820 accept - - # everything else - reject with icmp type port-unreachable - } - chain forward { - type filter hook forward priority 0; - - # allow from loopback and internal nic - ${allowSafe} - - # allow established/related connections - ${allowSafeOif} - - # Drop everything else - drop - } - chain output { - type filter hook output priority 0 - # dont allow any trafic from iot and stuff to escape to the wild - ${dropUnsafe} - } - } - table ip nat { - chain prerouting { - type nat hook prerouting priority 0 - ${portForwards} - } - - chain postrouting { - type nat hook postrouting priority 0 - - oifname ${waninterface} masquerade - } - } - ''; - - services.dnsmasq = { - enable = true; - alwaysKeepRunning = true; - extraConfig = - let - inherit (pkgs) runCommand; - gen = obj: '' - interface=${obj.name} - dhcp-range=${obj.name},${obj.dhcpv4start},${obj.dhcpv4end},12h - ''; - - genHosts = obj: '' - dhcp-host=${obj.mac},${obj.ip},${obj.name} - ''; - genall = builtins.concatStringsSep "\n" (map gen nets); - genallHosts = builtins.concatStringsSep "\n" (map genHosts cfg.staticDHCPs); - genstatics = builtins.concatStringsSep "\n" (map (a: "address=/${a.name}/${a.ip}") statics); - netbootxyz = builtins.fetchurl { - url = "https://github.com/netbootxyz/netboot.xyz/releases/download/2.0.40/netboot.xyz.efi"; - sha256 = "1gvgvlaxhjkr9i0b2bjq85h12ni9h5fn6r8nphsag3il9kificcc"; - }; - netbootxyzpath = runCommand "netbootpath" { } '' - mkdir $out - ln -s ${netbootxyz} $out/netbootxyz.efi - ''; - in - '' - no-resolv - # unbound broke - # server=127.0.0.1#5353 # unbound - server=1.1.1.1 - server=1.0.0.1 - - # https://hveem.no/using-dnsmasq-for-dhcpv6 - - # don't ever listen to anything on wan and stuff - except-interface=${waninterface},${laninterface} - - listen-address=0.0.0.0,:: - - # don't send bogus requests out on the internets - bogus-priv - - # enable IPv6 Route Advertisements - enable-ra - - # Construct a valid IPv6 range from reading the address set on the interface. The :: part refers to the ifid in dhcp6c.conf. Make sure you get this right or dnsmasq will get confused. - dhcp-range=lan,::,constructor:lan, ra-names,slaac, 12h - - # ra-names enables a mode which gives DNS names to dual-stack hosts which do SLAAC for IPv6. - # Add your local-only LAN domain - local=/${domain}/ - - # have your simple hosts expanded to domain - expand-hosts - - # set your domain for expand-hosts - domain=${domain} - - # forward .kube domains to coredns - server=/kube/10.13.0.10 - - - ${genall} - '' + - optionalString wgEnabled '' - interface=wg0 - no-dhcp-interface=wg0 - addn-hosts=/run/wireguard-hosts - '' + '' - interface=lo # otherwise localhost dns does not work - ${genstatics} - ${genallHosts} - - dhcp-boot=netbootxyz.efi - - enable-tftp - tftp-root=${netbootxyzpath} - - # set authoritative mode - dhcp-authoritative - - ''; - - }; - }; -}