From bda1a6b603a3944223707a6d090622b574ea7505 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Fri, 29 Jul 2022 11:07:19 +0200 Subject: bump & vpn --- hosts/surtr/vpn/default.nix | 177 +++++++++++++++++++++++++++++++++++++++++ hosts/surtr/vpn/geri.pub | 1 + hosts/surtr/vpn/ruleset.nft | 189 ++++++++++++++++++++++++++++++++++++++++++++ hosts/surtr/vpn/surtr.priv | 26 ++++++ hosts/surtr/vpn/surtr.pub | 1 + 5 files changed, 394 insertions(+) create mode 100644 hosts/surtr/vpn/default.nix create mode 100644 hosts/surtr/vpn/geri.pub create mode 100644 hosts/surtr/vpn/ruleset.nft create mode 100644 hosts/surtr/vpn/surtr.priv create mode 100644 hosts/surtr/vpn/surtr.pub (limited to 'hosts/surtr/vpn') diff --git a/hosts/surtr/vpn/default.nix b/hosts/surtr/vpn/default.nix new file mode 100644 index 00000000..4f334105 --- /dev/null +++ b/hosts/surtr/vpn/default.nix @@ -0,0 +1,177 @@ +{ pkgs, config, lib, ... }: + +with lib; + +let + trim = str: if hasSuffix "\n" str then trim (removeSuffix "\n" str) else str; + prefix4 = "10.84.47"; + prefix6 = "2a03:4000:52:ada:5"; +in { + config = { + boot.kernel.sysctl = { + "net.netfilter.nf_log_all_netns" = true; + }; + + networking.namespaces = { + enable = true; + containers."vpn".config = { + boot.kernel.sysctl = { + "net.core.rmem_max" = "4194304"; + "net.core.wmem_max" = "4194304"; + }; + + environment = { + noXlibs = true; + systemPackages = with pkgs; [ wireguard-tools ]; + }; + + networking = { + useDHCP = false; + useNetworkd = true; + useHostResolvConf = false; + firewall.enable = false; + nftables = { + enable = true; + rulesetFile = ./ruleset.nft; + }; + }; + + services.resolved.fallbackDns = [ + "9.9.9.9#dns.quad9.net" + "149.112.112.112#dns.quad9.net" + "2620:fe::fe#dns.quad9.net" + "2620:fe::9#dns.quad9.net" + ]; + + systemd.tmpfiles.rules = [ + "d /etc/wireguard 0755 root systemd-network - -" + "C /etc/wireguard/surtr.priv 0640 root systemd-network - /run/host/credentials/surtr.priv" + ]; + + systemd.network = { + netdevs = { + vpn = { + netdevConfig = { + Name = "vpn"; + Kind = "wireguard"; + }; + wireguardConfig = { + PrivateKeyFile = "/etc/wireguard/surtr.priv"; + ListenPort = 51820; + }; + wireguardPeers = [ + { wireguardPeerConfig = { + AllowedIPs = ["${prefix6}:1::/96" "${prefix4}.1/32"]; + PublicKey = trim (readFile ./geri.pub); + }; + } + ]; + }; + }; + + networks = { + upstream = { + name = "upstream"; + matchConfig = { + Name = "upstream"; + }; + linkConfig = { + RequiredForOnline = true; + }; + networkConfig = { + Address = [ "185.243.10.86/32" "2a03:4000:20:259::/64" ]; + LLMNR = false; + MulticastDNS = false; + }; + routes = [ + { routeConfig = { + Destination = "202.61.240.0/22"; + }; + } + { routeConfig = { + Destination = "0.0.0.0/0"; + Gateway = "202.61.240.1"; + }; + } + { routeConfig = { + Destination = "::/0"; + Gateway = "fe80::1"; + }; + } + ]; + extraConfig = '' + [Neighbor] + Address=202.61.240.1 + LinkLayerAddress=00:00:5e:00:01:01 + ''; + }; + vpn = { + name = "vpn"; + matchConfig = { + Name = "vpn"; + }; + address = ["${prefix6}::/96" "${prefix4}.0/32"]; + routes = [ + { routeConfig = { + Destination = "${prefix6}::/80"; + }; + } + { routeConfig = { + Destination = "${prefix4}.0/24"; + }; + } + ]; + linkConfig = { + RequiredForOnline = false; + }; + networkConfig = { + LLMNR = false; + MulticastDNS = false; + }; + }; + }; + }; + }; + }; + + systemd.services = { + "vpn-upstream" = { + bindsTo = ["netns@vpn.service"]; + after = ["netns@vpn.service"]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStop = "${pkgs.iproute}/bin/ip netns exec vpn ip link delete upstream"; + }; + path = with pkgs; [ iproute procps ]; + script = '' + ip netns exec vpn sysctl \ + net.ipv6.conf.all.forwarding=1 \ + net.ipv6.conf.default.forwarding=1 \ + net.ipv4.conf.all.forwarding=1 \ + net.ipv4.conf.default.forwarding=1 + + ip link add link ens3 name upstream type ipvlan mode l2 + ip link set upstream netns vpn + ''; + }; + + "netns-container@vpn" = { + wantedBy = ["multi-user.target" "network-online.target"]; + after = ["vpn-upstream.service"]; + bindsTo = ["vpn-upstream.service"]; + + serviceConfig = { + LoadCredential = [ + "surtr.priv:${config.sops.secrets.vpn.path}" + ]; + }; + }; + }; + + sops.secrets.vpn = { + format = "binary"; + sopsFile = ./surtr.priv; + }; + }; +} diff --git a/hosts/surtr/vpn/geri.pub b/hosts/surtr/vpn/geri.pub new file mode 100644 index 00000000..ed5de2b2 --- /dev/null +++ b/hosts/surtr/vpn/geri.pub @@ -0,0 +1 @@ +sYuQSNZHzfegv8HRz71jnZm2nFLGeRnaGwVonhKUj2k= diff --git a/hosts/surtr/vpn/ruleset.nft b/hosts/surtr/vpn/ruleset.nft new file mode 100644 index 00000000..3cdb7a8a --- /dev/null +++ b/hosts/surtr/vpn/ruleset.nft @@ -0,0 +1,189 @@ +define icmp_protos = {ipv6-icmp, icmp, igmp} + +table arp filter { + limit lim_arp { + rate over 50 mbytes/second burst 50 mbytes + } + + counter arp-rx {} + counter arp-tx {} + + counter arp-ratelimit-rx {} + counter arp-ratelimit-tx {} + + chain input { + type filter hook input priority filter + policy accept + + limit name lim_arp counter name arp-ratelimit-rx drop + + counter name arp-rx + } + + chain output { + type filter hook output priority filter + policy accept + + limit name lim_arp counter name arp-ratelimit-tx drop + + counter name arp-tx + } +} + +table inet filter { + limit lim_reject { + rate over 1000/second burst 1000 packets + } + + limit lim_icmp { + rate over 50 mbytes/second burst 50 mbytes + } + + counter invalid-fw {} + counter fw-lo {} + counter fw-vpn {} + counter fw-upstream {} + + counter icmp-ratelimit-upstream-fw {} + counter icmp-ratelimit-vpn-fw {} + counter icmp-ratelimit-established-fw {} + + counter icmp-upstream-fw {} + counter icmp-vpn-fw {} + counter icmp-established-fw {} + + counter reject-ratelimit-fw {} + counter reject-fw {} + counter reject-tcp-fw {} + counter reject-icmp-fw {} + + counter drop-fw {} + + counter invalid-rx {} + + counter rx-lo {} + counter invalid-local4-rx {} + counter invalid-local6-rx {} + + counter icmp-ratelimit-rx {} + counter icmp-rx {} + + counter wg-rx {} + + counter established-rx {} + + counter reject-ratelimit-rx {} + counter reject-rx {} + counter reject-tcp-rx {} + counter reject-icmp-rx {} + + counter drop-rx {} + + counter tx-lo {} + + counter icmp-ratelimit-tx {} + counter icmp-tx {} + + counter wg-tx {} + + counter tx {} + + chain forward { + type filter hook forward priority filter + policy drop + + + ct state invalid log level debug prefix "vpn: drop invalid forward: " counter name invalid-fw drop + + + iifname lo counter name fw-lo accept + + meta l4proto $icmp_protos iifname upstream limit name lim_icmp counter name icmp-ratelimit-upstream-fw drop + meta l4proto $icmp_protos iifname upstream counter name icmp-upstream-fw accept + meta l4proto $icmp_protos iifname vpn limit name lim_icmp counter name icmp-ratelimit-vpn-fw drop + meta l4proto $icmp_protos iifname vpn counter name icmp-vpn-fw accept + meta l4proto $icmp_protos ct state {established, related} limit name lim_icmp counter name icmp-ratelimit-established-fw drop + meta l4proto $icmp_protos ct state {established, related} counter name icmp-established-fw accept + + + iifname upstream oifname vpn ct state {established, related} counter name fw-vpn accept + iifname vpn oifname upstream counter name fw-upstream accept + + + limit name lim_reject log level debug prefix "vpn: drop forward: " counter name reject-ratelimit-fw drop + log level debug prefix "vpn: reject forward: " counter name reject-fw + meta l4proto tcp ct state new counter name reject-tcp-fw reject with tcp reset + ct state new counter name reject-icmp-fw reject + + + counter name drop-fw + } + + chain input { + type filter hook input priority filter + policy drop + + + ct state invalid log level debug prefix "vpn: drop invalid input: " counter name invalid-rx drop + + + iifname lo counter name rx-lo accept + iif != lo ip daddr 127.0.0.1/8 counter name invalid-local4-rx reject + iif != lo ip6 daddr ::1/128 counter name invalid-local6-rx reject + + meta l4proto $icmp_protos limit name lim_icmp counter name icmp-ratelimit-rx drop + meta l4proto $icmp_protos counter name icmp-rx accept + + udp dport 51820 counter name wg-rx accept + + ct state {established, related} counter name established-rx accept + + + limit name lim_reject log level debug prefix "vpn: drop input: " counter name reject-ratelimit-rx drop + log level debug prefix "vpn: reject input: " counter name reject-rx + meta l4proto tcp ct state new counter name reject-tcp-rx reject with tcp reset + ct state new counter name reject-icmp-rx reject + + + counter name drop-rx + } + + chain output { + type filter hook output priority filter + policy accept + + + oifname lo counter name tx-lo accept + + meta l4proto $icmp_protos limit name lim_icmp counter name icmp-ratelimit-tx drop + meta l4proto $icmp_protos counter name icmp-tx accept + + + udp sport 51820 counter name wg-tx + + + counter name tx + } +} + +table inet nat { + counter nat {} + + chain postrouting { + type nat hook postrouting priority srcnat + policy accept + + iifname vpn counter name nat masquerade + } +} + +table ip mss_clamp { + counter mss-clamp {} + + chain postrouting { + type filter hook postrouting priority mangle + policy accept + + iifname vpn oifname upstream tcp flags & (syn|rst) == syn counter name mss-clamp tcp option maxseg size set rt mtu + } +} \ No newline at end of file diff --git a/hosts/surtr/vpn/surtr.priv b/hosts/surtr/vpn/surtr.priv new file mode 100644 index 00000000..707287f5 --- /dev/null +++ b/hosts/surtr/vpn/surtr.priv @@ -0,0 +1,26 @@ +{ + "data": "ENC[AES256_GCM,data:dhGFzsKjzYTfFwxrcCGTVPKQoy12RDLfIqdBcxO7/aib90w/yfTWBQP2zNRa,iv:71HbOJRbpzLxYWztxzvM/qJNLdJQckaZVDOIAl5UKjI=,tag:JjF2zr78zjI7RPXqQaHmyg==,type:str]", + "sops": { + "kms": null, + "gcp_kms": null, + "azure_kv": null, + "hc_vault": null, + "age": null, + "lastmodified": "2022-07-28T19:09:57Z", + "mac": "ENC[AES256_GCM,data:Q2179Mp3h/FXVzM1T5sRfci+mo/gCGfUm5824GBTbCzwIsTMjSpPz/wByg0WQJ/WB3wnns+VfCh+epqnKcP73KKUmNysGNJ9DH1hNukmTWMZEI309yLE/GgDs76xGyt9hXdHClq30qhKT17bXQ7Pq08c437vfSwSCcKoKOcr6Ls=,iv:u81NRHwKSKb7Nfz2gC1tjdYlfrFETjF/gEMGAha4Y7g=,tag:zdxYtbiKtY46MGP/nO8S5w==,type:str]", + "pgp": [ + { + "created_at": "2022-07-28T19:09:57Z", + "enc": "-----BEGIN PGP MESSAGE-----\n\nhF4DXxoViZlp6dISAQdAa7ohlS2wGvuH11I4GvYZQmKbQVZUcwpV1XX6YMvLQV0w\n8fMshflTFWUnmHAR5ERg6ZpESFiAXAlkUMTLIZBhDTAN92jCu7+nnNFK1QgBVE07\n0lwBilABJT++m953o6ic4h/9yeyx5Wc6+XxS3d1Mc4qgNBzX/TBVEoKmuUgkHwET\nd0nftLYbKmICgCBgDgllWJLSOU4XSksmYIeMwiSpyNzv8oKz8u73SZz20rJ9kQ==\n=phWI\n-----END PGP MESSAGE-----\n", + "fp": "30D3453B8CD02FE2A3E7C78C0FB536FB87AE8F51" + }, + { + "created_at": "2022-07-28T19:09:57Z", + "enc": "-----BEGIN PGP MESSAGE-----\n\nhF4DyFKFNkTVG5oSAQdAV4pW8CJP/QP0S/w5e7S/Xrox+Ix/NBvw2N2fWp+5FwAw\nATp3d/QGyk+vwuQpQj3zq/cEzrWrrq19Gl+UUjSyI2rkpUnxWboA2xICYVkb91Oz\n0lwBLu54X/3X5Nd2krPv+Qa7AWPBKF6BkE2PIjjrvPgyJ4/XiFzawJsILH37QPqs\n7PcrteF15UNR416omVNZoWpF3Tq/j4Jw+ewRhU9WjOXe2GO8/X9zjTD9fRrpIQ==\n=YtV+\n-----END PGP MESSAGE-----\n", + "fp": "7ED22F4AA7BB55728B643DC5471B7D88E4EF66F8" + } + ], + "unencrypted_suffix": "_unencrypted", + "version": "3.7.3" + } +} \ No newline at end of file diff --git a/hosts/surtr/vpn/surtr.pub b/hosts/surtr/vpn/surtr.pub new file mode 100644 index 00000000..48edc8fc --- /dev/null +++ b/hosts/surtr/vpn/surtr.pub @@ -0,0 +1 @@ +99nWsdE/KJHfOZjmG5suUQSfIj6UBuxS5+zOL+ynYmU= -- cgit v1.2.3