about summary refs log tree commit diff
path: root/nixos/modules/services/networking
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/services/networking')
-rw-r--r--nixos/modules/services/networking/dnscache.nix6
-rw-r--r--nixos/modules/services/networking/mihomo.nix118
-rw-r--r--nixos/modules/services/networking/mycelium.nix133
-rw-r--r--nixos/modules/services/networking/networkmanager.nix22
4 files changed, 275 insertions, 4 deletions
diff --git a/nixos/modules/services/networking/dnscache.nix b/nixos/modules/services/networking/dnscache.nix
index eff13f69f470..4f5b77a5b685 100644
--- a/nixos/modules/services/networking/dnscache.nix
+++ b/nixos/modules/services/networking/dnscache.nix
@@ -86,7 +86,11 @@ in {
 
   config = mkIf config.services.dnscache.enable {
     environment.systemPackages = [ pkgs.djbdns ];
-    users.users.dnscache.isSystemUser = true;
+    users.users.dnscache = {
+        isSystemUser = true;
+        group = "dnscache";
+    };
+    users.groups.dnscache = {};
 
     systemd.services.dnscache = {
       description = "djbdns dnscache server";
diff --git a/nixos/modules/services/networking/mihomo.nix b/nixos/modules/services/networking/mihomo.nix
new file mode 100644
index 000000000000..ae700603b529
--- /dev/null
+++ b/nixos/modules/services/networking/mihomo.nix
@@ -0,0 +1,118 @@
+# NOTE:
+# cfg.configFile contains secrets such as proxy servers' credential!
+# we dont want plaintext secrets in world-readable `/nix/store`.
+
+{ lib
+, config
+, pkgs
+, ...
+}:
+let
+  cfg = config.services.mihomo;
+in
+{
+  options.services.mihomo = {
+    enable = lib.mkEnableOption "Mihomo, A rule-based proxy in Go.";
+
+    package = lib.mkPackageOption pkgs "mihomo" { };
+
+    configFile = lib.mkOption {
+      default = null;
+      type = lib.types.nullOr lib.types.path;
+      description = "Configuration file to use.";
+    };
+
+    webui = lib.mkOption {
+      default = null;
+      type = lib.types.nullOr lib.types.path;
+      description = ''
+        Local web interface to use.
+
+        You can also use the following website, just in case:
+        - metacubexd:
+          - https://d.metacubex.one
+          - https://metacubex.github.io/metacubexd
+          - https://metacubexd.pages.dev
+        - yacd:
+          - https://yacd.haishan.me
+        - clash-dashboard (buggy):
+          - https://clash.razord.top
+      '';
+    };
+
+    extraOpts = lib.mkOption {
+      default = null;
+      type = lib.types.nullOr lib.types.str;
+      description = "Extra command line options to use.";
+    };
+
+    tunMode = lib.mkEnableOption ''
+      necessary permission for Mihomo's systemd service for TUN mode to function properly.
+
+      Keep in mind, that you still need to enable TUN mode manually in Mihomo's configuration.
+    '';
+  };
+
+  config = lib.mkIf cfg.enable {
+    ### systemd service
+    systemd.services."mihomo" = {
+      description = "Mihomo daemon, A rule-based proxy in Go.";
+      documentation = [ "https://wiki.metacubex.one/" ];
+      requires = [ "network-online.target" ];
+      after = [ "network-online.target" ];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig =
+        {
+          ExecStart = lib.concatStringsSep " " [
+            (lib.getExe cfg.package)
+            "-d /var/lib/private/mihomo"
+            (lib.optionalString (cfg.configFile != null) "-f \${CREDENTIALS_DIRECTORY}/config.yaml")
+            (lib.optionalString (cfg.webui != null) "-ext-ui ${cfg.webui}")
+            (lib.optionalString (cfg.extraOpts != null) cfg.extraOpts)
+          ];
+
+          DynamicUser = true;
+          StateDirectory = "mihomo";
+          LoadCredential = "config.yaml:${cfg.configFile}";
+
+          ### Hardening
+          AmbientCapabilities = "";
+          CapabilityBoundingSet = "";
+          DeviceAllow = "";
+          LockPersonality = true;
+          MemoryDenyWriteExecute = true;
+          NoNewPrivileges = true;
+          PrivateDevices = true;
+          PrivateMounts = true;
+          PrivateTmp = true;
+          PrivateUsers = true;
+          ProcSubset = "pid";
+          ProtectClock = true;
+          ProtectControlGroups = true;
+          ProtectHome = true;
+          ProtectHostname = true;
+          ProtectKernelLogs = true;
+          ProtectKernelModules = true;
+          ProtectKernelTunables = true;
+          ProtectProc = "invisible";
+          ProtectSystem = "strict";
+          RestrictRealtime = true;
+          RestrictSUIDSGID = true;
+          RestrictNamespaces = true;
+          RestrictAddressFamilies = "AF_INET AF_INET6";
+          SystemCallArchitectures = "native";
+          SystemCallFilter = "@system-service bpf";
+          UMask = "0077";
+        }
+        // lib.optionalAttrs cfg.tunMode {
+          AmbientCapabilities = "CAP_NET_ADMIN";
+          CapabilityBoundingSet = "CAP_NET_ADMIN";
+          PrivateDevices = false;
+          PrivateUsers = false;
+          RestrictAddressFamilies = "AF_INET AF_INET6 AF_NETLINK";
+        };
+    };
+  };
+
+  meta.maintainers = with lib.maintainers; [ Guanran928 ];
+}
diff --git a/nixos/modules/services/networking/mycelium.nix b/nixos/modules/services/networking/mycelium.nix
new file mode 100644
index 000000000000..9c4bca7c6861
--- /dev/null
+++ b/nixos/modules/services/networking/mycelium.nix
@@ -0,0 +1,133 @@
+{ config, pkgs, lib, ... }:
+
+let
+  cfg = config.services.mycelium;
+in
+{
+  options.services.mycelium = {
+    enable = lib.mkEnableOption "mycelium network";
+    peers = lib.mkOption {
+      type = lib.types.listOf lib.types.str;
+      description = ''
+        List of peers to connect to, in the formats:
+         - `quic://[2001:0db8::1]:9651`
+         - `quic://192.0.2.1:9651`
+         - `tcp://[2001:0db8::1]:9651`
+         - `tcp://192.0.2.1:9651`
+
+        If addHostedPublicNodes is set to true, the hosted public nodes will also be added.
+      '';
+      default = [ ];
+    };
+    keyFile = lib.mkOption {
+      type = lib.types.nullOr lib.types.path;
+      default = null;
+      description = ''
+        Optional path to a file containing the mycelium key material.
+        If unset, the default location (`/var/lib/mycelium/key.bin`) will be used.
+        If no key exist at this location, it will be generated on startup.
+      '';
+    };
+    openFirewall = lib.mkOption {
+      type = lib.types.bool;
+      default = false;
+      description = "Open the firewall for mycelium";
+    };
+    package = lib.mkOption {
+      type = lib.types.package;
+      default = pkgs.mycelium;
+      defaultText = lib.literalExpression ''"''${pkgs.mycelium}"'';
+      description = "The mycelium package to use";
+    };
+    addHostedPublicNodes = lib.mkOption {
+      type = lib.types.bool;
+      default = true;
+      description = ''
+        Adds the hosted peers from https://github.com/threefoldtech/mycelium#hosted-public-nodes.
+      '';
+    };
+  };
+  config = lib.mkIf cfg.enable {
+    networking.firewall.allowedTCPPorts = lib.optionals cfg.openFirewall [ 9651 ];
+    networking.firewall.allowedUDPPorts = lib.optionals cfg.openFirewall [ 9650 9651 ];
+
+    systemd.services.mycelium = {
+      description = "Mycelium network";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      restartTriggers = [
+        cfg.keyFile
+      ];
+
+      unitConfig.Documentation = "https://github.com/threefoldtech/mycelium";
+
+      serviceConfig = {
+        User = "mycelium";
+        DynamicUser = true;
+        StateDirectory = "mycelium";
+        ProtectHome = true;
+        ProtectSystem = true;
+        LoadCredential = lib.mkIf (cfg.keyFile != null) "keyfile:${cfg.keyFile}";
+        SyslogIdentifier = "mycelium";
+        AmbientCapabilities = [ "CAP_NET_ADMIN" ];
+        MemoryDenyWriteExecute = true;
+        ProtectControlGroups = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK";
+        RestrictNamespaces = true;
+        RestrictRealtime = true;
+        SystemCallArchitectures = "native";
+        SystemCallFilter = [ "@system-service" "~@privileged @keyring" ];
+        ExecStart = lib.concatStringsSep " " ([
+          (lib.getExe cfg.package)
+          (if (cfg.keyFile != null) then
+            "--key-file \${CREDENTIALS_DIRECTORY}/keyfile" else
+            "--key-file %S/mycelium/key.bin"
+          )
+          "--tun-name"
+          "mycelium"
+        ] ++
+        (lib.optional (cfg.addHostedPublicNodes || cfg.peers != [ ]) "--peers")
+        ++ cfg.peers ++ (lib.optionals cfg.addHostedPublicNodes [
+          "tcp://188.40.132.242:9651" # DE 01
+          "tcp://[2a01:4f8:221:1e0b::2]:9651"
+          "quic://188.40.132.242:9651"
+          "quic://[2a01:4f8:221:1e0b::2]:9651"
+
+          "tcp://136.243.47.186:9651" # DE 02
+          "tcp://[2a01:4f8:212:fa6::2]:9651"
+          "quic://136.243.47.186:9651"
+          "quic://[2a01:4f8:212:fa6::2]:9651"
+
+          "tcp://185.69.166.7:9651" # BE 03
+          "tcp://[2a02:1802:5e:0:8478:51ff:fee2:3331]:9651"
+          "quic://185.69.166.7:9651"
+          "quic://[2a02:1802:5e:0:8478:51ff:fee2:3331]:9651"
+
+          "tcp://185.69.166.8:9651" # BE 04
+          "tcp://[2a02:1802:5e:0:8c9e:7dff:fec9:f0d2]:9651"
+          "quic://185.69.166.8:9651"
+          "quic://[2a02:1802:5e:0:8c9e:7dff:fec9:f0d2]:9651"
+
+          "tcp://65.21.231.58:9651" # FI 05
+          "tcp://[2a01:4f9:6a:1dc5::2]:9651"
+          "quic://65.21.231.58:9651"
+          "quic://[2a01:4f9:6a:1dc5::2]:9651"
+
+          "tcp://65.109.18.113:9651" # FI 06
+          "tcp://[2a01:4f9:5a:1042::2]:9651"
+          "quic://65.109.18.113:9651"
+          "quic://[2a01:4f9:5a:1042::2]:9651"
+        ]));
+        Restart = "always";
+        RestartSec = 5;
+        TimeoutStopSec = 5;
+      };
+    };
+  };
+  meta = {
+    maintainers = with lib.maintainers; [ flokli lassulus ];
+  };
+}
+
diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix
index b7f0d9373608..573a02cbda9e 100644
--- a/nixos/modules/services/networking/networkmanager.nix
+++ b/nixos/modules/services/networking/networkmanager.nix
@@ -101,7 +101,23 @@ let
     pre-down = "pre-down.d/";
   };
 
-  macAddressOpt = mkOption {
+  macAddressOptWifi = mkOption {
+    type = types.either types.str (types.enum [ "permanent" "preserve" "random" "stable" "stable-ssid" ]);
+    default = "preserve";
+    example = "00:11:22:33:44:55";
+    description = lib.mdDoc ''
+      Set the MAC address of the interface.
+
+      - `"XX:XX:XX:XX:XX:XX"`: MAC address of the interface
+      - `"permanent"`: Use the permanent MAC address of the device
+      - `"preserve"`: Don’t change the MAC address of the device upon activation
+      - `"random"`: Generate a randomized value upon each connect
+      - `"stable"`: Generate a stable, hashed MAC address
+      - `"stable-ssid"`: Generate a stable MAC addressed based on Wi-Fi network
+    '';
+  };
+
+  macAddressOptEth = mkOption {
     type = types.either types.str (types.enum [ "permanent" "preserve" "random" "stable" ]);
     default = "preserve";
     example = "00:11:22:33:44:55";
@@ -258,10 +274,10 @@ in
         '';
       };
 
-      ethernet.macAddress = macAddressOpt;
+      ethernet.macAddress = macAddressOptEth;
 
       wifi = {
-        macAddress = macAddressOpt;
+        macAddress = macAddressOptWifi;
 
         backend = mkOption {
           type = types.enum [ "wpa_supplicant" "iwd" ];