From 5c8d143a516b57c6693c6319aef36dd5e80eab9b Mon Sep 17 00:00:00 2001 From: Yingchi Long Date: Wed, 27 Dec 2023 10:51:16 +0800 Subject: [PATCH 1/3] nixos/modules/clash: refactor rules under services.clash --- nixos/configurations/adrastea/networking.nix | 2 +- nixos/configurations/aplaz/default.nix | 2 +- nixos/configurations/metis/default.nix | 3 +- nixos/modules/clash/default.nix | 68 ++++++++++++++++++-- nixos/modules/clash/rule.nix | 50 -------------- nixos/modules/default.nix | 1 - 6 files changed, 68 insertions(+), 58 deletions(-) delete mode 100644 nixos/modules/clash/rule.nix diff --git a/nixos/configurations/adrastea/networking.nix b/nixos/configurations/adrastea/networking.nix index bca34c6..bd84da4 100644 --- a/nixos/configurations/adrastea/networking.nix +++ b/nixos/configurations/adrastea/networking.nix @@ -70,6 +70,6 @@ in services.clash = { enable = true; - configPath = config.sops.templates."clash-config.yaml".path; + rule.enable = true; }; } diff --git a/nixos/configurations/aplaz/default.nix b/nixos/configurations/aplaz/default.nix index 5c53f2c..93e3131 100644 --- a/nixos/configurations/aplaz/default.nix +++ b/nixos/configurations/aplaz/default.nix @@ -31,7 +31,7 @@ services.clash = { enable = true; - configPath = config.sops.templates."clash-config.yaml".path; + rule.enable = true; }; services.resolved.enable = true; diff --git a/nixos/configurations/metis/default.nix b/nixos/configurations/metis/default.nix index 9c12b6d..29c4503 100644 --- a/nixos/configurations/metis/default.nix +++ b/nixos/configurations/metis/default.nix @@ -18,7 +18,8 @@ services.clash = { enable = true; - configPath = config.sops.templates."clash-config.yaml".path; + rule.enable = true; + rule.enableTUN = true; }; inclyc.user.enable = true; diff --git a/nixos/modules/clash/default.nix b/nixos/modules/clash/default.nix index abed212..2603e64 100644 --- a/nixos/modules/clash/default.nix +++ b/nixos/modules/clash/default.nix @@ -37,10 +37,13 @@ in example = "users"; type = types.str; }; + rule = { + enable = mkEnableOption "clash rule generation"; + enableTUN = mkEnableOption "TUN interface"; + }; }; - config = - mkIf cfg.enable { - + config = lib.mkMerge [ + (mkIf cfg.enable { users.users = optionalAttrs (cfg.user == defaultUser) { ${defaultUser} = { @@ -80,5 +83,62 @@ in AmbientCapabilities = CapabilityBoundingSet; }; }; - }; + }) + (mkIf cfg.rule.enable ( + let + providers = [ "dler" "mielink" "bywave" ]; + proxyProviders = lib.genAttrs providers (name: { + type = "http"; + path = "./${name}.yaml"; + url = "${config.sops.placeholder."clash-provider/${name}"}"; + interval = 3600; + health-check = { + enable = true; + url = "http://www.gstatic.com/generate_204"; + interval = 300; + }; + }); + proxyGroups = [ + { + name = "Proxy"; + type = "select"; + use = providers; + proxies = [ + "Auto" + "DIRECT" + ]; + } + { + name = "Auto"; + type = "url-test"; + use = providers; + proxies = [ "DIRECT" ]; + url = "http://cp.cloudflare.com/generate_204"; + interval = "3600"; + } + ] ++ builtins.fromJSON (builtins.readFile ./proxy-groups.json); + in + { + services.clash.configPath = lib.mkDefault config.sops.templates."clash-config.yaml".path; + sops.secrets = lib.attrsets.mergeAttrsList (map + (name: { + "clash-provider/${name}" = { }; + }) + providers); + sops.templates."clash-config.yaml".content = builtins.readFile ./rule.yaml + '' + proxy-groups: ${builtins.toJSON proxyGroups} + proxy-providers: ${builtins.toJSON proxyProviders} + '' + (lib.optionalString cfg.rule.enableTUN '' + tun: + enable: true + stack: system + auto-route: true + auto-detect-interface: true + ''); + + sops.templates."clash-config.yaml".owner = cfg.user; + sops.templates."clash-config.yaml".group = cfg.group; + } + )) + ]; } diff --git a/nixos/modules/clash/rule.nix b/nixos/modules/clash/rule.nix deleted file mode 100644 index 3087754..0000000 --- a/nixos/modules/clash/rule.nix +++ /dev/null @@ -1,50 +0,0 @@ -{ lib, config, ... }: -let - providers = [ "dler" "mielink" "bywave" ]; - - mkProvider = name: { - type = "http"; - path = "./${name}.yaml"; - url = "${config.sops.placeholder."clash-provider/${name}"}"; - interval = 3600; - health-check = { - enable = true; - url = "http://www.gstatic.com/generate_204"; - interval = 300; - }; - }; - mkSecret = name: { - "clash-provider/${name}" = { }; - }; - - proxyProviders = lib.genAttrs providers mkProvider; - - proxyGroups = [ - { - name = "Proxy"; - type = "select"; - use = providers; - proxies = [ - "Auto" - "DIRECT" - ]; - } - { - name = "Auto"; - type = "url-test"; - use = providers; - proxies = [ "DIRECT" ]; - url = "http://cp.cloudflare.com/generate_204"; - interval = "3600"; - } - ] ++ builtins.fromJSON (builtins.readFile ./proxy-groups.json); -in -{ - sops.secrets = lib.attrsets.mergeAttrsList (map mkSecret providers); - sops.templates."clash-config.yaml".content = builtins.readFile ./rule.yaml + '' - proxy-groups: ${builtins.toJSON proxyGroups} - proxy-providers: ${builtins.toJSON proxyProviders} - ''; - - sops.templates."clash-config.yaml".owner = config.services.clash.user; -} diff --git a/nixos/modules/default.nix b/nixos/modules/default.nix index 653019d..cc47db2 100644 --- a/nixos/modules/default.nix +++ b/nixos/modules/default.nix @@ -4,7 +4,6 @@ imports = [ inputs.home-manager.nixosModules.home-manager ./clash - ./clash/rule.nix ./nix.nix ./ddns.nix ./nix-ld.nix From b9ca3611b029f59ac42e95d2ac7e9546a3a0f167 Mon Sep 17 00:00:00 2001 From: Yingchi Long Date: Wed, 27 Dec 2023 20:26:41 +0800 Subject: [PATCH 2/3] nixos/modules/clash: unify clash 204 service URL --- nixos/modules/clash/default.nix | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nixos/modules/clash/default.nix b/nixos/modules/clash/default.nix index 2603e64..881f7dd 100644 --- a/nixos/modules/clash/default.nix +++ b/nixos/modules/clash/default.nix @@ -86,6 +86,7 @@ in }) (mkIf cfg.rule.enable ( let + generate_204 = "http://www.gstatic.com/generate_204"; providers = [ "dler" "mielink" "bywave" ]; proxyProviders = lib.genAttrs providers (name: { type = "http"; @@ -94,7 +95,7 @@ in interval = 3600; health-check = { enable = true; - url = "http://www.gstatic.com/generate_204"; + url = generate_204; interval = 300; }; }); @@ -113,7 +114,7 @@ in type = "url-test"; use = providers; proxies = [ "DIRECT" ]; - url = "http://cp.cloudflare.com/generate_204"; + url = generate_204; interval = "3600"; } ] ++ builtins.fromJSON (builtins.readFile ./proxy-groups.json); From 51a6ed091517da2f1cba73893a4f14db8ec71d11 Mon Sep 17 00:00:00 2001 From: Yingchi Long Date: Wed, 27 Dec 2023 20:27:38 +0800 Subject: [PATCH 3/3] nixos/modules/clash: use DynamicUser & hardening flags Thanks @@YHNdnzj for the suggestion. --- nixos/modules/clash/default.nix | 54 +++++++++------------------------ 1 file changed, 15 insertions(+), 39 deletions(-) diff --git a/nixos/modules/clash/default.nix b/nixos/modules/clash/default.nix index 881f7dd..1d9e5f6 100644 --- a/nixos/modules/clash/default.nix +++ b/nixos/modules/clash/default.nix @@ -6,7 +6,6 @@ with lib; let cfg = config.services.clash; - defaultUser = "clash"; in { options.services.clash = { @@ -26,17 +25,6 @@ in configPath = mkOption { type = types.path; }; - user = mkOption { - default = defaultUser; - example = "john"; - type = types.str; - }; - - group = mkOption { - default = defaultUser; - example = "users"; - type = types.str; - }; rule = { enable = mkEnableOption "clash rule generation"; enableTUN = mkEnableOption "TUN interface"; @@ -44,43 +32,34 @@ in }; config = lib.mkMerge [ (mkIf cfg.enable { - users.users = optionalAttrs (cfg.user == defaultUser) { - ${defaultUser} = - { - description = "clash user"; - group = defaultUser; - uid = config.ids.uids.znc; - isSystemUser = true; - }; - }; - - users.groups = optionalAttrs (cfg.user == defaultUser) { - ${defaultUser} = - { - gid = config.ids.gids.znc; - members = [ defaultUser ]; - }; - }; - systemd.services.clash = { - wantedBy = [ "multi-user.target" ]; after = [ "systemd-networkd-wait-online.service" ]; description = "Clash Daemon"; - serviceConfig = rec { Type = "simple"; - User = cfg.user; - Group = cfg.group; - PrivateTmp = true; + DynamicUser = "yes"; + LoadCredential = "config.yaml:${cfg.configPath}"; WorkingDirectory = "${cfg.workingDirectory}"; ExecStartPre = "${pkgs.coreutils}/bin/ln -s ${pkgs.clash-geoip}/etc/clash/Country.mmdb ${cfg.configDirectory}"; ExecStart = "${lib.getExe cfg.package}" + " -d ${cfg.configDirectory}" - + " -f ${cfg.configPath}"; + + " -f %d/config.yaml"; Restart = "on-failure"; CapabilityBoundingSet = [ "CAP_NET_ADMIN" "CAP_NET_RAW" "CAP_NET_BIND_SERVICE" ]; AmbientCapabilities = CapabilityBoundingSet; + ProtectSystem = "strict"; + ProtectHome = "yes"; + PrivateDevices = "yes"; + PrivateUsers = "yes"; + ProtectHostname = "yes"; + ProtectClock = "yes"; + ProtectKernelTunables = "yes"; + ProtectKernelModules = "yes"; + ProtectKernelLogs = "yes"; + ProtectControlGroups = "yes"; + ProtectProc = "yes"; + LockPersonality = "yes"; }; }; }) @@ -136,9 +115,6 @@ in auto-route: true auto-detect-interface: true ''); - - sops.templates."clash-config.yaml".owner = cfg.user; - sops.templates."clash-config.yaml".group = cfg.group; } )) ];