Commit 351be58

HPCesia <me@hpcesia.com>
2025-08-04 14:06:56
refactor: mihomo config
1 parent b19f22d
modules/nixos/base/mihomo/config/default.nix
@@ -0,0 +1,20 @@
+{mylib, ...}: {
+  imports = mylib.scanModules ./.;
+
+  services.mihomo.config = {
+    mixed-port = 7154;
+    allow-lan = true;
+    mode = "rule";
+    log-level = "warning";
+    ipv6 = false;
+    find-process-mode = "strict";
+    external-controller = "127.0.0.1:9090";
+    unified-delay = true;
+    tcp-concurrent = true;
+    global-client-fingerprint = "chrome";
+    profile = {
+      store-selected = true;
+      store-fake-ip = true;
+    };
+  };
+}
modules/nixos/base/mihomo/config/dns.nix
@@ -0,0 +1,40 @@
+{...}: {
+  services.mihomo.config.dns = {
+    enable = true;
+    prefer-h3 = true;
+    ipv6 = false;
+    enhanced-mode = "fake-ip";
+    fake-ip-range = "198.18.0.1/16";
+    fake-ip-filter = [
+      "+.+m2m"
+      "+.$injections.adguard.org"
+      "+.$local.adguard.org"
+      "+.+bogon"
+      "+.+lan"
+      "+.+local"
+      "+.+localdomain"
+      "+.home.arpa"
+      "dns.msftncsi.com"
+      "*.srv.nintendo.net"
+      "*.stun.playstation.net"
+      "xbox.*.microsoft.com"
+      "*.xboxlive.com"
+      "*.turn.twilio.com"
+      "*.stun.twilio.com"
+      "stun.syncthing.net"
+      "stun.*"
+      "*.sslip.io"
+      "*.nip.io"
+    ];
+    respect-rules = true;
+    nameserver = [
+      "system"
+      "https://223.5.5.5/dns-query"
+      "https://doh.pub/dns-query"
+    ];
+    proxy-server-nameserver = [
+      "https://223.5.5.5/dns-query"
+      "https://doh.pub/dns-query"
+    ];
+  };
+}
modules/nixos/base/mihomo/config/proxy-groups.nix
@@ -0,0 +1,210 @@
+{...}: let
+  FilterHK = "^(?=.*((?i)๐Ÿ‡ญ๐Ÿ‡ฐ|้ฆ™ๆธฏ|\\b(HK|Hong)(\\d+)?\\b))(?!.*((?i)ๅ›žๅ›ฝ|ๆ กๅ›ญ|็ฝ‘็ซ™|ๅœฐๅ€|ๅ‰ฉไฝ™|่ฟ‡ๆœŸ|ๆ—ถ้—ด|ๆœ‰ๆ•ˆ|็ฝ‘ๅ€|็ฆๆญข|้‚ฎ็ฎฑ|ๅ‘ๅธƒ|ๅฎขๆœ|่ฎข้˜…|่Š‚็‚น)).*$";
+  FilterTW = "^(?=.*((?i)๐Ÿ‡น๐Ÿ‡ผ|ๅฐๆนพ|\\b(TW|Tai|Taiwan)(\\d+)?\\b))(?!.*((?i)ๅ›žๅ›ฝ|ๆ กๅ›ญ|็ฝ‘็ซ™|ๅœฐๅ€|ๅ‰ฉไฝ™|่ฟ‡ๆœŸ|ๆ—ถ้—ด|ๆœ‰ๆ•ˆ|็ฝ‘ๅ€|็ฆๆญข|้‚ฎ็ฎฑ|ๅ‘ๅธƒ|ๅฎขๆœ|่ฎข้˜…|่Š‚็‚น)).*$";
+  FilterJP = "^(?=.*((?i)๐Ÿ‡ฏ๐Ÿ‡ต|ๆ—ฅๆœฌ|ๅทๆ—ฅ|ไธœไบฌ|ๅคง้˜ช|ๆณ‰ๆ—ฅ|ๅŸผ็މ|\\b(JP|Japan)(\\d+)?\\b))(?!.*((?i)ๅ›žๅ›ฝ|ๆ กๅ›ญ|็ฝ‘็ซ™|ๅœฐๅ€|ๅ‰ฉไฝ™|่ฟ‡ๆœŸ|ๆ—ถ้—ด|ๆœ‰ๆ•ˆ|็ฝ‘ๅ€|็ฆๆญข|้‚ฎ็ฎฑ|ๅ‘ๅธƒ|ๅฎขๆœ|่ฎข้˜…|่Š‚็‚น)).*$";
+  FilterKR = "^(?=.*((?i)๐Ÿ‡ฐ๐Ÿ‡ท|้Ÿฉๅ›ฝ|้Ÿ“|้ฆ–ๅฐ”|\\b(KR|Korea)(\\d+)?\\b))(?!.*((?i)ๅ›žๅ›ฝ|ๆ กๅ›ญ|็ฝ‘็ซ™|ๅœฐๅ€|ๅ‰ฉไฝ™|่ฟ‡ๆœŸ|ๆ—ถ้—ด|ๆœ‰ๆ•ˆ|็ฝ‘ๅ€|็ฆๆญข|้‚ฎ็ฎฑ|ๅ‘ๅธƒ|ๅฎขๆœ|่ฎข้˜…|่Š‚็‚น)).*$";
+  FilterSG = "^(?=.*((?i)๐Ÿ‡ธ๐Ÿ‡ฌ|ๆ–ฐๅŠ ๅก|็‹ฎ|\\b(SG|Singapore)(\\d+)?\\b))(?!.*((?i)ๅ›žๅ›ฝ|ๆ กๅ›ญ|็ฝ‘็ซ™|ๅœฐๅ€|ๅ‰ฉไฝ™|่ฟ‡ๆœŸ|ๆ—ถ้—ด|ๆœ‰ๆ•ˆ|็ฝ‘ๅ€|็ฆๆญข|้‚ฎ็ฎฑ|ๅ‘ๅธƒ|ๅฎขๆœ|่ฎข้˜…|่Š‚็‚น)).*$";
+  FilterUS = "^(?=.*((?i)๐Ÿ‡บ๐Ÿ‡ธ|็พŽๅ›ฝ|ๆณข็‰นๅ…ฐ|่พพๆ‹‰ๆ–ฏ|ไฟ„ๅ‹’ๅ†ˆ|ๅ‡คๅ‡ฐๅŸŽ|่ดนๅˆฉ่’™|็ก…่ฐท|ๆ‹‰ๆ–ฏ็ปดๅŠ ๆ–ฏ|ๆด›ๆ‰็Ÿถ|ๅœฃไฝ•ๅกž|ๅœฃๅ…‹ๆ‹‰ๆ‹‰|่ฅฟ้›…ๅ›พ|่ŠๅŠ ๅ“ฅ|\\b(US|United States)(\\d+)?\\b))(?!.*((?i)ๅ›žๅ›ฝ|ๆ กๅ›ญ|็ฝ‘็ซ™|ๅœฐๅ€|ๅ‰ฉไฝ™|่ฟ‡ๆœŸ|ๆ—ถ้—ด|ๆœ‰ๆ•ˆ|็ฝ‘ๅ€|็ฆๆญข|้‚ฎ็ฎฑ|ๅ‘ๅธƒ|ๅฎขๆœ|่ฎข้˜…|่Š‚็‚น)).*$";
+  FilterUK = "^(?=.*((?i)๐Ÿ‡ฌ๐Ÿ‡ง|่‹ฑๅ›ฝ|ไผฆๆ•ฆ|\\b(UK|United Kingdom)(\\d+)?\\b))(?!.*((?i)ๅ›žๅ›ฝ|ๆ กๅ›ญ|็ฝ‘็ซ™|ๅœฐๅ€|ๅ‰ฉไฝ™|่ฟ‡ๆœŸ|ๆ—ถ้—ด|ๆœ‰ๆ•ˆ|็ฝ‘ๅ€|็ฆๆญข|้‚ฎ็ฎฑ|ๅ‘ๅธƒ|ๅฎขๆœ|่ฎข้˜…|่Š‚็‚น)).*$";
+  FilterFR = "^(?=.*((?i)๐Ÿ‡ซ๐Ÿ‡ท|ๆณ•ๅ›ฝ|\\b(FR|France)(\\d+)?\\b))(?!.*((?i)ๅ›žๅ›ฝ|ๆ กๅ›ญ|็ฝ‘็ซ™|ๅœฐๅ€|ๅ‰ฉไฝ™|่ฟ‡ๆœŸ|ๆ—ถ้—ด|ๆœ‰ๆ•ˆ|็ฝ‘ๅ€|็ฆๆญข|้‚ฎ็ฎฑ|ๅ‘ๅธƒ|ๅฎขๆœ|่ฎข้˜…|่Š‚็‚น)).*$";
+  FilterDE = "^(?=.*((?i)๐Ÿ‡ฉ๐Ÿ‡ช|ๅพทๅ›ฝ|\\b(DE|Germany)(\\d+)?\\b))(?!.*((?i)ๅ›žๅ›ฝ|ๆ กๅ›ญ|็ฝ‘็ซ™|ๅœฐๅ€|ๅ‰ฉไฝ™|่ฟ‡ๆœŸ|ๆ—ถ้—ด|ๆœ‰ๆ•ˆ|็ฝ‘ๅ€|็ฆๆญข|้‚ฎ็ฎฑ|ๅ‘ๅธƒ|ๅฎขๆœ|่ฎข้˜…|่Š‚็‚น)).*$";
+  FilterOthers = "^(?!.*(๐Ÿ‡ญ๐Ÿ‡ฐ|HK|Hong|้ฆ™ๆธฏ|๐Ÿ‡น๐Ÿ‡ผ|TW|Taiwan|Wan|๐Ÿ‡ฏ๐Ÿ‡ต|JP|Japan|ๆ—ฅๆœฌ|๐Ÿ‡ธ๐Ÿ‡ฌ|SG|Singapore|็‹ฎๅŸŽ|๐Ÿ‡บ๐Ÿ‡ธ|US|United States|America|็พŽๅ›ฝ|๐Ÿ‡ฉ๐Ÿ‡ช|DE|Germany|ๅพทๅ›ฝ|๐Ÿ‡ฌ๐Ÿ‡ง|UK|United Kingdom|่‹ฑๅ›ฝ|๐Ÿ‡ฐ๐Ÿ‡ท|KR|Korea|้Ÿฉๅ›ฝ|้Ÿ“|๐Ÿ‡ซ๐Ÿ‡ท|FR|France|ๆณ•ๅ›ฝ)).*$";
+  FilterAll = "^(?=.*(.))(?!.*((?i)็พค|้‚€่ฏท|่ฟ”ๅˆฉ|ๅพช็Žฏ|ๅฎ˜็ฝ‘|ๅฎขๆœ|็ฝ‘็ซ™|็ฝ‘ๅ€|่Žทๅ–|่ฎข้˜…|ๆต้‡|ๅˆฐๆœŸ|ๆœบๅœบ|ไธ‹ๆฌก|็‰ˆๆœฌ|ๅฎ˜ๅ€|ๅค‡็”จ|่ฟ‡ๆœŸ|ๅทฒ็”จ|่”็ณป|้‚ฎ็ฎฑ|ๅทฅๅ•|่ดฉๅ–|้€š็Ÿฅ|ๅ€’ๅ–|้˜ฒๆญข|ๅ›ฝๅ†…|ๅœฐๅ€|้ข‘้“|ๆ— ๆณ•|่ฏดๆ˜Ž|ไฝฟ็”จ|ๆ็คบ|็‰นๅˆซ|่ฎฟ้—ฎ|ๆ”ฏๆŒ|ๆ•™็จ‹|ๅ…ณๆณจ|ๆ›ดๆ–ฐ|ไฝœ่€…|ๅŠ ๅ…ฅ|(\\b(USE|USED|TOTAL|EXPIRE|EMAIL|Panel|Channel|Author)\\b|(\\d{4}-\\d{2}-\\d{2}|\\d+G)))).*$";
+
+  Select = {
+    type = "select";
+    url = "http://connectivitycheck.platform.hicloud.com/generate_204";
+    disable-udp = false;
+    hidden = false;
+    include-all = true;
+  };
+  Auto = {
+    type = "url-test";
+    url = "http://connectivitycheck.platform.hicloud.com/generate_204";
+    interval = 300;
+    tolerance = 50;
+    disable-udp = false;
+    hidden = true;
+    include-all = true;
+  };
+in {
+  services.mihomo.config.proxy-groups =
+    [
+      # ไธป้€‰ๆ‹ฉ็ป„
+      {
+        name = "๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ";
+        type = "select";
+        proxies = ["่‡ชๅŠจ้€‰ๆ‹ฉ" "ๆ‰‹ๅŠจ้€‰ๆ‹ฉ" "DIRECT"];
+        url = "http://connectivitycheck.platform.hicloud.com/generate_204";
+        icon = "https://raw.githubusercontent.com/Orz-3/mini/master/Color/Static.png";
+      }
+      # ๆ‰‹ๅŠจ/่‡ชๅŠจ
+      {
+        name = "ๆ‰‹ๅŠจ้€‰ๆ‹ฉ";
+        type = "select";
+        proxies = [
+          "๐Ÿ‡ญ๐Ÿ‡ฐ - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ"
+          "๐Ÿ‡ฏ๐Ÿ‡ต - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ"
+          "๐Ÿ‡ฐ๐Ÿ‡ท - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ"
+          "๐Ÿ‡ธ๐Ÿ‡ฌ - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ"
+          "๐Ÿ‡บ๐Ÿ‡ธ - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ"
+          "๐Ÿ‡ฌ๐Ÿ‡ง - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ"
+          "๐Ÿ‡ซ๐Ÿ‡ท - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ"
+          "๐Ÿ‡ฉ๐Ÿ‡ช - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ"
+          "๐Ÿ‡น๐Ÿ‡ผ - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ"
+          "Others - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ"
+        ];
+        url = "http://connectivitycheck.platform.hicloud.com/generate_204";
+        icon = "https://raw.githubusercontent.com/Orz-3/mini/master/Color/Cylink.png";
+      }
+      {
+        name = "่‡ชๅŠจ้€‰ๆ‹ฉ";
+        type = "select";
+        proxies = [
+          "๐Ÿ‡ญ๐Ÿ‡ฐ - ่‡ชๅŠจ้€‰ๆ‹ฉ"
+          "๐Ÿ‡ฏ๐Ÿ‡ต - ่‡ชๅŠจ้€‰ๆ‹ฉ"
+          "๐Ÿ‡ฐ๐Ÿ‡ท - ่‡ชๅŠจ้€‰ๆ‹ฉ"
+          "๐Ÿ‡ธ๐Ÿ‡ฌ - ่‡ชๅŠจ้€‰ๆ‹ฉ"
+          "๐Ÿ‡บ๐Ÿ‡ธ - ่‡ชๅŠจ้€‰ๆ‹ฉ"
+          "๐Ÿ‡ฌ๐Ÿ‡ง - ่‡ชๅŠจ้€‰ๆ‹ฉ"
+          "๐Ÿ‡ซ๐Ÿ‡ท - ่‡ชๅŠจ้€‰ๆ‹ฉ"
+          "๐Ÿ‡ฉ๐Ÿ‡ช - ่‡ชๅŠจ้€‰ๆ‹ฉ"
+          "๐Ÿ‡น๐Ÿ‡ผ - ่‡ชๅŠจ้€‰ๆ‹ฉ"
+        ];
+        url = "http://connectivitycheck.platform.hicloud.com/generate_204";
+        icon = "https://raw.githubusercontent.com/Orz-3/mini/master/Color/Urltest.png";
+      }
+      # ๅบ”็”จๅˆ†็ป„
+      {
+        name = "โœˆ๏ธ ็”ตๆŠฅไฟกๆฏ";
+        type = "select";
+        proxies = [
+          "๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ"
+          "๐Ÿ‡ญ๐Ÿ‡ฐ - ่‡ชๅŠจ้€‰ๆ‹ฉ"
+          "๐Ÿ‡ฏ๐Ÿ‡ต - ่‡ชๅŠจ้€‰ๆ‹ฉ"
+          "๐Ÿ‡ธ๐Ÿ‡ฌ - ่‡ชๅŠจ้€‰ๆ‹ฉ"
+          "๐Ÿ‡บ๐Ÿ‡ธ - ่‡ชๅŠจ้€‰ๆ‹ฉ"
+        ];
+        icon = "https://raw.githubusercontent.com/Orz-3/mini/master/Color/Telegram.png";
+      }
+      {
+        name = "๐Ÿค– AIGC";
+        type = "select";
+        proxies = [
+          "๐Ÿ‡บ๐Ÿ‡ธ - ่‡ชๅŠจ้€‰ๆ‹ฉ"
+          "๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ"
+          "๐Ÿ‡ญ๐Ÿ‡ฐ - ่‡ชๅŠจ้€‰ๆ‹ฉ"
+          "๐Ÿ‡ฏ๐Ÿ‡ต - ่‡ชๅŠจ้€‰ๆ‹ฉ"
+          "๐Ÿ‡ธ๐Ÿ‡ฌ - ่‡ชๅŠจ้€‰ๆ‹ฉ"
+        ];
+        icon = "https://raw.githubusercontent.com/Orz-3/mini/master/Color/OpenAI.png";
+      }
+      {
+        name = "๐ŸŽ ่‹นๆžœๆœๅŠก";
+        type = "select";
+        proxies = ["DIRECT" "๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ" "๐Ÿ‡ญ๐Ÿ‡ฐ - ่‡ชๅŠจ้€‰ๆ‹ฉ" "๐Ÿ‡บ๐Ÿ‡ธ - ่‡ชๅŠจ้€‰ๆ‹ฉ"];
+        icon = "https://raw.githubusercontent.com/Orz-3/mini/master/Color/Apple.png";
+      }
+      {
+        name = "โ“‚๏ธ ๅพฎ่ฝฏๆœๅŠก";
+        type = "select";
+        proxies = ["DIRECT" "๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ" "๐Ÿ‡ญ๐Ÿ‡ฐ - ่‡ชๅŠจ้€‰ๆ‹ฉ" "๐Ÿ‡บ๐Ÿ‡ธ - ่‡ชๅŠจ้€‰ๆ‹ฉ"];
+        icon = "https://raw.githubusercontent.com/Orz-3/mini/master/Color/Microsoft.png";
+      }
+    ]
+    ++ (map (x: Auto // x) [
+      # ่‡ชๅŠจ้€‰ๆ‹ฉ - ๆŒ‰ๅœฐๅŒบ
+      {
+        name = "๐Ÿ‡ญ๐Ÿ‡ฐ - ่‡ชๅŠจ้€‰ๆ‹ฉ";
+        filter = FilterHK;
+      }
+      {
+        name = "๐Ÿ‡ฏ๐Ÿ‡ต - ่‡ชๅŠจ้€‰ๆ‹ฉ";
+        filter = FilterJP;
+      }
+      {
+        name = "๐Ÿ‡ฐ๐Ÿ‡ท - ่‡ชๅŠจ้€‰ๆ‹ฉ";
+        filter = FilterKR;
+      }
+      {
+        name = "๐Ÿ‡ธ๐Ÿ‡ฌ - ่‡ชๅŠจ้€‰ๆ‹ฉ";
+        filter = FilterSG;
+      }
+      {
+        name = "๐Ÿ‡บ๐Ÿ‡ธ - ่‡ชๅŠจ้€‰ๆ‹ฉ";
+        filter = FilterUS;
+      }
+      {
+        name = "๐Ÿ‡ฌ๐Ÿ‡ง - ่‡ชๅŠจ้€‰ๆ‹ฉ";
+        filter = FilterUK;
+      }
+      {
+        name = "๐Ÿ‡ซ๐Ÿ‡ท - ่‡ชๅŠจ้€‰ๆ‹ฉ";
+        filter = FilterFR;
+      }
+      {
+        name = "๐Ÿ‡ฉ๐Ÿ‡ช - ่‡ชๅŠจ้€‰ๆ‹ฉ";
+        filter = FilterDE;
+      }
+      {
+        name = "๐Ÿ‡น๐Ÿ‡ผ - ่‡ชๅŠจ้€‰ๆ‹ฉ";
+        filter = FilterTW;
+      }
+    ])
+    ++ (map (x: Select // x) [
+      # ๆ‰‹ๅŠจ้€‰ๆ‹ฉ - ๆŒ‰ๅœฐๅŒบ
+      {
+        name = "๐Ÿ‡ญ๐Ÿ‡ฐ - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ";
+        filter = FilterHK;
+      }
+      {
+        name = "๐Ÿ‡ฏ๐Ÿ‡ต - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ";
+        filter = FilterJP;
+      }
+      {
+        name = "๐Ÿ‡ฐ๐Ÿ‡ท - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ";
+        filter = FilterKR;
+      }
+      {
+        name = "๐Ÿ‡ธ๐Ÿ‡ฌ - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ";
+        filter = FilterSG;
+      }
+      {
+        name = "๐Ÿ‡บ๐Ÿ‡ธ - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ";
+        filter = FilterUS;
+      }
+      {
+        name = "๐Ÿ‡ฌ๐Ÿ‡ง - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ";
+        filter = FilterUK;
+      }
+      {
+        name = "๐Ÿ‡ซ๐Ÿ‡ท - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ";
+        filter = FilterFR;
+      }
+      {
+        name = "๐Ÿ‡ฉ๐Ÿ‡ช - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ";
+        filter = FilterDE;
+      }
+      {
+        name = "๐Ÿ‡น๐Ÿ‡ผ - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ";
+        filter = FilterTW;
+      }
+      {
+        name = "Others - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ";
+        filter = FilterOthers;
+      }
+    ])
+    ++ [
+      # ๅ…จ้ƒจ่Š‚็‚น
+      (Select
+        // {
+          name = "AllIn - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ";
+          filter = FilterAll;
+        })
+      (Auto
+        // {
+          name = "AllIn - ่‡ชๅŠจ้€‰ๆ‹ฉ";
+          filter = FilterAll;
+        })
+    ];
+}
modules/nixos/base/mihomo/config/proxy-providers.nix
@@ -0,0 +1,28 @@
+{config, ...}: let
+  NodeParam = {
+    type = "http";
+    interval = 86400;
+    health-check = {
+      enable = true;
+      url = "http://cp.cloudflare.com";
+      interval = 300;
+    };
+  };
+in {
+  services.mihomo.config.proxy-providers = {
+    "Node-YiYuan" =
+      NodeParam
+      // {
+        url = config.sops.placeholder."mihomo/providers/yi_yuan";
+        path = "./proxy_provider/providers-yi_yuan.yaml";
+        override.additional-prefix = "[YY]";
+      };
+    "Node-MoJie" =
+      NodeParam
+      // {
+        url = config.sops.placeholder."mihomo/providers/mo_jie";
+        path = "./proxy_provider/providers-mo_jie.yaml";
+        override.additional-prefix = "[MJ]";
+      };
+  };
+}
modules/nixos/base/mihomo/config/rules.nix
@@ -0,0 +1,227 @@
+{...}: let
+  RuleSet_classical = {
+    type = "http";
+    behavior = "classical";
+    interval = 43200;
+    format = "text";
+    proxy = "๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ";
+  };
+  RuleSet_domain = {
+    type = "http";
+    behavior = "domain";
+    interval = 43200;
+    format = "text";
+    proxy = "๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ";
+  };
+  RuleSet_ipcidr = {
+    type = "http";
+    behavior = "ipcidr";
+    interval = 43200;
+    format = "text";
+    proxy = "๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ";
+  };
+in {
+  services.mihomo.config = {
+    rules = [
+      # ่‡ช่ฎข็ฑป่ง„ๅˆ™
+      "AND,((RULE-SET,my_services),(DST-PORT,80/443)),๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ"
+      "RULE-SET,my_services,DIRECT"
+      # ้ž IP ็ฑป่ง„ๅˆ™
+      "RULE-SET,reject_non_ip,REJECT"
+      "RULE-SET,reject_domainset,REJECT"
+      "RULE-SET,reject_non_ip_drop,REJECT-DROP"
+      "RULE-SET,reject_non_ip_no_drop,REJECT"
+      "RULE-SET,cdn_domainset,๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ"
+      "RULE-SET,cdn_non_ip,๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ"
+      "RULE-SET,stream_non_ip,๐Ÿ‡บ๐Ÿ‡ธ - ่‡ชๅŠจ้€‰ๆ‹ฉ"
+      "RULE-SET,telegram_non_ip,โœˆ๏ธ ็”ตๆŠฅไฟกๆฏ"
+      "RULE-SET,apple_cdn,DIRECT"
+      "RULE-SET,download_domainset,๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ"
+      "RULE-SET,download_non_ip,๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ"
+      "RULE-SET,microsoft_cdn_non_ip,DIRECT"
+      "RULE-SET,apple_cn_non_ip,DIRECT"
+      "RULE-SET,apple_services,๐ŸŽ ่‹นๆžœๆœๅŠก"
+      "RULE-SET,microsoft_non_ip,โ“‚๏ธ ๅพฎ่ฝฏๆœๅŠก"
+      "RULE-SET,ai_non_ip,๐Ÿค– AIGC"
+      "RULE-SET,global_non_ip,๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ"
+      "RULE-SET,domestic_non_ip,DIRECT"
+      "RULE-SET,direct_non_ip,DIRECT"
+      "RULE-SET,lan_non_ip,DIRECT"
+      # IP ็ฑป่ง„ๅˆ™
+      "RULE-SET,reject_ip,REJECT"
+      "RULE-SET,telegram_ip,โœˆ๏ธ ็”ตๆŠฅไฟกๆฏ"
+      "RULE-SET,stream_ip,๐Ÿ‡บ๐Ÿ‡ธ - ่‡ชๅŠจ้€‰ๆ‹ฉ"
+      "RULE-SET,lan_ip,DIRECT"
+      "RULE-SET,domestic_ip,DIRECT"
+      "RULE-SET,china_ip,DIRECT"
+      "MATCH,๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ"
+    ];
+    rule-providers = {
+      reject_non_ip_no_drop =
+        RuleSet_classical
+        // {
+          url = "https://ruleset.skk.moe/Clash/non_ip/reject-no-drop.txt";
+          path = "./rule_set/sukkaw_ruleset/reject_non_ip_no_drop.txt";
+        };
+      reject_non_ip_drop =
+        RuleSet_classical
+        // {
+          url = "https://ruleset.skk.moe/Clash/non_ip/reject-drop.txt";
+          path = "./rule_set/sukkaw_ruleset/reject_non_ip_drop.txt";
+        };
+      reject_non_ip =
+        RuleSet_classical
+        // {
+          url = "https://ruleset.skk.moe/Clash/non_ip/reject.txt";
+          path = "./rule_set/sukkaw_ruleset/reject_non_ip.txt";
+        };
+      reject_domainset =
+        RuleSet_domain
+        // {
+          url = "https://ruleset.skk.moe/Clash/domainset/reject.txt";
+          path = "./rule_set/sukkaw_ruleset/reject_domainset.txt";
+        };
+      reject_ip =
+        RuleSet_classical
+        // {
+          url = "https://ruleset.skk.moe/Clash/ip/reject.txt";
+          path = "./rule_set/sukkaw_ruleset/reject_ip.txt";
+        };
+      cdn_domainset =
+        RuleSet_domain
+        // {
+          url = "https://ruleset.skk.moe/Clash/domainset/cdn.txt";
+          path = "./rule_set/sukkaw_ruleset/cdn_domainset.txt";
+        };
+      cdn_non_ip =
+        RuleSet_domain
+        // {
+          url = "https://ruleset.skk.moe/Clash/non_ip/cdn.txt";
+          path = "./rule_set/sukkaw_ruleset/cdn_non_ip.txt";
+        };
+      stream_non_ip =
+        RuleSet_classical
+        // {
+          url = "https://ruleset.skk.moe/Clash/non_ip/stream.txt";
+          path = "./rule_set/sukkaw_ruleset/stream_non_ip.txt";
+        };
+      stream_ip =
+        RuleSet_classical
+        // {
+          url = "https://ruleset.skk.moe/Clash/ip/stream.txt";
+          path = "./rule_set/sukkaw_ruleset/stream_ip.txt";
+        };
+      ai_non_ip =
+        RuleSet_classical
+        // {
+          url = "https://ruleset.skk.moe/Clash/non_ip/ai.txt";
+          path = "./rule_set/sukkaw_ruleset/ai_non_ip.txt";
+        };
+      telegram_non_ip =
+        RuleSet_classical
+        // {
+          url = "https://ruleset.skk.moe/Clash/non_ip/telegram.txt";
+          path = "./rule_set/sukkaw_ruleset/telegram_non_ip.txt";
+        };
+      telegram_ip =
+        RuleSet_classical
+        // {
+          url = "https://ruleset.skk.moe/Clash/ip/telegram.txt";
+          path = "./rule_set/sukkaw_ruleset/telegram_ip.txt";
+        };
+      apple_cdn =
+        RuleSet_domain
+        // {
+          url = "https://ruleset.skk.moe/Clash/domainset/apple_cdn.txt";
+          path = "./rule_set/sukkaw_ruleset/apple_cdn.txt";
+        };
+      apple_services =
+        RuleSet_classical
+        // {
+          url = "https://ruleset.skk.moe/Clash/non_ip/apple_services.txt";
+          path = "./rule_set/sukkaw_ruleset/apple_services.txt";
+        };
+      apple_cn_non_ip =
+        RuleSet_classical
+        // {
+          url = "https://ruleset.skk.moe/Clash/non_ip/apple_cn.txt";
+          path = "./rule_set/sukkaw_ruleset/apple_cn_non_ip.txt";
+        };
+      microsoft_cdn_non_ip =
+        RuleSet_classical
+        // {
+          url = "https://ruleset.skk.moe/Clash/non_ip/microsoft_cdn.txt";
+          path = "./rule_set/sukkaw_ruleset/microsoft_cdn_non_ip.txt";
+        };
+      microsoft_non_ip =
+        RuleSet_classical
+        // {
+          url = "https://ruleset.skk.moe/Clash/non_ip/microsoft.txt";
+          path = "./rule_set/sukkaw_ruleset/microsoft_non_ip.txt";
+        };
+      download_domainset =
+        RuleSet_domain
+        // {
+          url = "https://ruleset.skk.moe/Clash/domainset/download.txt";
+          path = "./rule_set/sukkaw_ruleset/download_domainset.txt";
+        };
+      download_non_ip =
+        RuleSet_domain
+        // {
+          url = "https://ruleset.skk.moe/Clash/non_ip/download.txt";
+          path = "./rule_set/sukkaw_ruleset/download_non_ip.txt";
+        };
+      lan_non_ip =
+        RuleSet_classical
+        // {
+          url = "https://ruleset.skk.moe/Clash/non_ip/lan.txt";
+          path = "./rule_set/sukkaw_ruleset/lan_non_ip.txt";
+        };
+      lan_ip =
+        RuleSet_classical
+        // {
+          url = "https://ruleset.skk.moe/Clash/ip/lan.txt";
+          path = "./rule_set/sukkaw_ruleset/lan_ip.txt";
+        };
+      domestic_non_ip =
+        RuleSet_classical
+        // {
+          url = "https://ruleset.skk.moe/Clash/non_ip/domestic.txt";
+          path = "./rule_set/sukkaw_ruleset/domestic_non_ip.txt";
+        };
+      direct_non_ip =
+        RuleSet_classical
+        // {
+          url = "https://ruleset.skk.moe/Clash/non_ip/direct.txt";
+          path = "./rule_set/sukkaw_ruleset/direct_non_ip.txt";
+        };
+      global_non_ip =
+        RuleSet_classical
+        // {
+          url = "https://ruleset.skk.moe/Clash/non_ip/global.txt";
+          path = "./rule_set/sukkaw_ruleset/global_non_ip.txt";
+        };
+      domestic_ip =
+        RuleSet_classical
+        // {
+          url = "https://ruleset.skk.moe/Clash/ip/domestic.txt";
+          path = "./rule_set/sukkaw_ruleset/domestic_ip.txt";
+        };
+      china_ip =
+        RuleSet_ipcidr
+        // {
+          url = "https://ruleset.skk.moe/Clash/ip/china_ip.txt";
+          path = "./rule_set/sukkaw_ruleset/china_ip.txt";
+        };
+      my_services = {
+        type = "inline";
+        behavior = "classical";
+        payload = [
+          "DOMAIN-SUFFIX,hpcesia.com"
+          "DOMAIN-SUFFIX,trin.one"
+          "DOMAIN-SUFFIX,mxrouting.net"
+        ];
+      };
+    };
+  };
+}
modules/nixos/base/mihomo/config/sniffer.nix
@@ -0,0 +1,21 @@
+{...}: {
+  services.mihomo.config.sniffer = {
+    enable = true;
+    sniff = {
+      HTTP = {
+        ports = [80 "8080-8880"];
+        override-destination = true;
+      };
+      TLS = {
+        ports = [443 8443];
+      };
+      QUIC = {
+        ports = [443 8443];
+      };
+    };
+    skip-domain = [
+      "Mijia Cloud"
+      "+.push.apple.com"
+    ];
+  };
+}
modules/nixos/base/mihomo/config/tun.nix
@@ -0,0 +1,15 @@
+{...}: {
+  services.mihomo.config.tun = {
+    enable = true;
+    stack = "mixed";
+    device = "ElysianRealm";
+    auto-route = true;
+    auto-detect-interface = true;
+    dns-hijack = [
+      "any:53"
+      "tcp://any:53"
+    ];
+    strict-route = true;
+    mtu = 1500;
+  };
+}
modules/nixos/base/mihomo/config.yaml
@@ -1,457 +0,0 @@
-# From https://github.com/yyhhyyyyyy/selfproxy
-
-mixed-port: 7154
-allow-lan: true
-mode: rule
-log-level: warning
-ipv6: false
-find-process-mode: strict
-external-controller: 127.0.0.1:9090
-unified-delay: true
-tcp-concurrent: true
-global-client-fingerprint: chrome
-
-profile:
-  store-selected: true
-  store-fake-ip: true
-
-dns:
-  enable: true
-  prefer-h3: true
-  ipv6: false
-  enhanced-mode: fake-ip
-  fake-ip-range: 198.18.0.1/16
-  fake-ip-filter:
-    - +.+m2m
-    - +.$injections.adguard.org
-    - +.$local.adguard.org
-    - +.+bogon
-    - +.+lan
-    - +.+local
-    - +.+localdomain
-    - +.home.arpa
-    - dns.msftncsi.com
-    - "*.srv.nintendo.net"
-    - "*.stun.playstation.net"
-    - xbox.*.microsoft.com
-    - "*.xboxlive.com"
-    - "*.turn.twilio.com"
-    - "*.stun.twilio.com"
-    - stun.syncthing.net
-    - stun.*
-    - "*.sslip.io"
-    - "*.nip.io"
-
-  respect-rules: true
-  nameserver:
-    - system
-    - https://223.5.5.5/dns-query
-    - https://doh.pub/dns-query
-  proxy-server-nameserver:
-    - https://223.5.5.5/dns-query
-    - https://doh.pub/dns-query
-
-sniffer:
-  enable: true
-  sniff:
-    HTTP:
-      ports: [80, 8080-8880]
-      override-destination: true
-    TLS:
-      ports: [443, 8443]
-    QUIC:
-      ports: [443, 8443]
-  skip-domain:
-    - "Mijia Cloud"
-    - "+.push.apple.com"
-
-tun:
-  enable: true
-  stack: mixed
-  device: ElysianRealm
-  auto-route: true
-  auto-detect-interface: true
-  dns-hijack:
-    - any:53
-    - tcp://any:53
-  strict-route: true
-  mtu: 1500
-
-# # ่ฎข้˜…้…็ฝฎ
-# # ่ฟ™้ƒจๅˆ†ๅœจ `default.nix` ไธญ้…็ฝฎ
-# NodeParam:
-#   &NodeParam {
-#     type: http,
-#     interval: 86400,
-#     health-check:
-#       { enable: true, url: "http://cp.cloudflare.com", interval: 300 },
-#   }
-# proxy-providers:
-#   Node-1:
-#     url: "<ๅ ไฝ็ฌฆ>"
-#     <<: *NodeParam
-#     path: "./proxy_provider/providers-1.yaml"
-#     override:
-#       additional-prefix: "[A] "
-#   Node-2:
-#     url: "<ๅ ไฝ็ฌฆ>"
-#     <<: *NodeParam
-#     path: "./proxy_provider/providers-2.yaml"
-#     override:
-#       additional-prefix: "[B] "
-
-# ่Š‚็‚น็ญ›้€‰
-# ๆŒ‰ๅœฐๅŒบ็ญ›้€‰
-FilterHK: &FilterHK '^(?=.*((?i)๐Ÿ‡ญ๐Ÿ‡ฐ|้ฆ™ๆธฏ|\b(HK|Hong)(\d+)?\b))(?!.*((?i)ๅ›žๅ›ฝ|ๆ กๅ›ญ|็ฝ‘็ซ™|ๅœฐๅ€|ๅ‰ฉไฝ™|่ฟ‡ๆœŸ|ๆ—ถ้—ด|ๆœ‰ๆ•ˆ|็ฝ‘ๅ€|็ฆๆญข|้‚ฎ็ฎฑ|ๅ‘ๅธƒ|ๅฎขๆœ|่ฎข้˜…|่Š‚็‚น)).*$'
-FilterTW: &FilterTW '^(?=.*((?i)๐Ÿ‡น๐Ÿ‡ผ|ๅฐๆนพ|\b(TW|Tai|Taiwan)(\d+)?\b))(?!.*((?i)ๅ›žๅ›ฝ|ๆ กๅ›ญ|็ฝ‘็ซ™|ๅœฐๅ€|ๅ‰ฉไฝ™|่ฟ‡ๆœŸ|ๆ—ถ้—ด|ๆœ‰ๆ•ˆ|็ฝ‘ๅ€|็ฆๆญข|้‚ฎ็ฎฑ|ๅ‘ๅธƒ|ๅฎขๆœ|่ฎข้˜…|่Š‚็‚น)).*$'
-FilterJP: &FilterJP '^(?=.*((?i)๐Ÿ‡ฏ๐Ÿ‡ต|ๆ—ฅๆœฌ|ๅทๆ—ฅ|ไธœไบฌ|ๅคง้˜ช|ๆณ‰ๆ—ฅ|ๅŸผ็މ|\b(JP|Japan)(\d+)?\b))(?!.*((?i)ๅ›žๅ›ฝ|ๆ กๅ›ญ|็ฝ‘็ซ™|ๅœฐๅ€|ๅ‰ฉไฝ™|่ฟ‡ๆœŸ|ๆ—ถ้—ด|ๆœ‰ๆ•ˆ|็ฝ‘ๅ€|็ฆๆญข|้‚ฎ็ฎฑ|ๅ‘ๅธƒ|ๅฎขๆœ|่ฎข้˜…|่Š‚็‚น)).*$'
-FilterKR: &FilterKR '^(?=.*((?i)๐Ÿ‡ฐ๐Ÿ‡ท|้Ÿฉๅ›ฝ|้Ÿ“|้ฆ–ๅฐ”|\b(KR|Korea)(\d+)?\b))(?!.*((?i)ๅ›žๅ›ฝ|ๆ กๅ›ญ|็ฝ‘็ซ™|ๅœฐๅ€|ๅ‰ฉไฝ™|่ฟ‡ๆœŸ|ๆ—ถ้—ด|ๆœ‰ๆ•ˆ|็ฝ‘ๅ€|็ฆๆญข|้‚ฎ็ฎฑ|ๅ‘ๅธƒ|ๅฎขๆœ|่ฎข้˜…|่Š‚็‚น)).*$'
-FilterSG: &FilterSG '^(?=.*((?i)๐Ÿ‡ธ๐Ÿ‡ฌ|ๆ–ฐๅŠ ๅก|็‹ฎ|\b(SG|Singapore)(\d+)?\b))(?!.*((?i)ๅ›žๅ›ฝ|ๆ กๅ›ญ|็ฝ‘็ซ™|ๅœฐๅ€|ๅ‰ฉไฝ™|่ฟ‡ๆœŸ|ๆ—ถ้—ด|ๆœ‰ๆ•ˆ|็ฝ‘ๅ€|็ฆๆญข|้‚ฎ็ฎฑ|ๅ‘ๅธƒ|ๅฎขๆœ|่ฎข้˜…|่Š‚็‚น)).*$'
-FilterUS: &FilterUS '^(?=.*((?i)๐Ÿ‡บ๐Ÿ‡ธ|็พŽๅ›ฝ|ๆณข็‰นๅ…ฐ|่พพๆ‹‰ๆ–ฏ|ไฟ„ๅ‹’ๅ†ˆ|ๅ‡คๅ‡ฐๅŸŽ|่ดนๅˆฉ่’™|็ก…่ฐท|ๆ‹‰ๆ–ฏ็ปดๅŠ ๆ–ฏ|ๆด›ๆ‰็Ÿถ|ๅœฃไฝ•ๅกž|ๅœฃๅ…‹ๆ‹‰ๆ‹‰|่ฅฟ้›…ๅ›พ|่ŠๅŠ ๅ“ฅ|\b(US|United States)(\d+)?\b))(?!.*((?i)ๅ›žๅ›ฝ|ๆ กๅ›ญ|็ฝ‘็ซ™|ๅœฐๅ€|ๅ‰ฉไฝ™|่ฟ‡ๆœŸ|ๆ—ถ้—ด|ๆœ‰ๆ•ˆ|็ฝ‘ๅ€|็ฆๆญข|้‚ฎ็ฎฑ|ๅ‘ๅธƒ|ๅฎขๆœ|่ฎข้˜…|่Š‚็‚น)).*$'
-FilterUK: &FilterUK '^(?=.*((?i)๐Ÿ‡ฌ๐Ÿ‡ง|่‹ฑๅ›ฝ|ไผฆๆ•ฆ|\b(UK|United Kingdom)(\d+)?\b))(?!.*((?i)ๅ›žๅ›ฝ|ๆ กๅ›ญ|็ฝ‘็ซ™|ๅœฐๅ€|ๅ‰ฉไฝ™|่ฟ‡ๆœŸ|ๆ—ถ้—ด|ๆœ‰ๆ•ˆ|็ฝ‘ๅ€|็ฆๆญข|้‚ฎ็ฎฑ|ๅ‘ๅธƒ|ๅฎขๆœ|่ฎข้˜…|่Š‚็‚น)).*$'
-FilterFR: &FilterFR '^(?=.*((?i)๐Ÿ‡ซ๐Ÿ‡ท|ๆณ•ๅ›ฝ|\b(FR|France)(\d+)?\b))(?!.*((?i)ๅ›žๅ›ฝ|ๆ กๅ›ญ|็ฝ‘็ซ™|ๅœฐๅ€|ๅ‰ฉไฝ™|่ฟ‡ๆœŸ|ๆ—ถ้—ด|ๆœ‰ๆ•ˆ|็ฝ‘ๅ€|็ฆๆญข|้‚ฎ็ฎฑ|ๅ‘ๅธƒ|ๅฎขๆœ|่ฎข้˜…|่Š‚็‚น)).*$'
-FilterDE: &FilterDE '^(?=.*((?i)๐Ÿ‡ฉ๐Ÿ‡ช|ๅพทๅ›ฝ|\b(DE|Germany)(\d+)?\b))(?!.*((?i)ๅ›žๅ›ฝ|ๆ กๅ›ญ|็ฝ‘็ซ™|ๅœฐๅ€|ๅ‰ฉไฝ™|่ฟ‡ๆœŸ|ๆ—ถ้—ด|ๆœ‰ๆ•ˆ|็ฝ‘ๅ€|็ฆๆญข|้‚ฎ็ฎฑ|ๅ‘ๅธƒ|ๅฎขๆœ|่ฎข้˜…|่Š‚็‚น)).*$'
-FilterOthers: &FilterOthers "^(?!.*(๐Ÿ‡ญ๐Ÿ‡ฐ|HK|Hong|้ฆ™ๆธฏ|๐Ÿ‡น๐Ÿ‡ผ|TW|Taiwan|Wan|๐Ÿ‡ฏ๐Ÿ‡ต|JP|Japan|ๆ—ฅๆœฌ|๐Ÿ‡ธ๐Ÿ‡ฌ|SG|Singapore|็‹ฎๅŸŽ|๐Ÿ‡บ๐Ÿ‡ธ|US|United States|America|็พŽๅ›ฝ|๐Ÿ‡ฉ๐Ÿ‡ช|DE|Germany|ๅพทๅ›ฝ|๐Ÿ‡ฌ๐Ÿ‡ง|UK|United Kingdom|่‹ฑๅ›ฝ|๐Ÿ‡ฐ๐Ÿ‡ท|KR|Korea|้Ÿฉๅ›ฝ|้Ÿ“|๐Ÿ‡ซ๐Ÿ‡ท|FR|France|ๆณ•ๅ›ฝ)).*$"
-FilterAll: &FilterAll '^(?=.*(.))(?!.*((?i)็พค|้‚€่ฏท|่ฟ”ๅˆฉ|ๅพช็Žฏ|ๅฎ˜็ฝ‘|ๅฎขๆœ|็ฝ‘็ซ™|็ฝ‘ๅ€|่Žทๅ–|่ฎข้˜…|ๆต้‡|ๅˆฐๆœŸ|ๆœบๅœบ|ไธ‹ๆฌก|็‰ˆๆœฌ|ๅฎ˜ๅ€|ๅค‡็”จ|่ฟ‡ๆœŸ|ๅทฒ็”จ|่”็ณป|้‚ฎ็ฎฑ|ๅทฅๅ•|่ดฉๅ–|้€š็Ÿฅ|ๅ€’ๅ–|้˜ฒๆญข|ๅ›ฝๅ†…|ๅœฐๅ€|้ข‘้“|ๆ— ๆณ•|่ฏดๆ˜Ž|ไฝฟ็”จ|ๆ็คบ|็‰นๅˆซ|่ฎฟ้—ฎ|ๆ”ฏๆŒ|ๆ•™็จ‹|ๅ…ณๆณจ|ๆ›ดๆ–ฐ|ไฝœ่€…|ๅŠ ๅ…ฅ|(\b(USE|USED|TOTAL|EXPIRE|EMAIL|Panel|Channel|Author)\b|(\d{4}-\d{2}-\d{2}|\d+G)))).*$'
-
-Select:
-  &Select {
-    type: select,
-    url: "http://connectivitycheck.platform.hicloud.com/generate_204",
-    disable-udp: false,
-    hidden: false,
-    include-all: true,
-  }
-Auto:
-  &Auto {
-    type: url-test,
-    url: "http://connectivitycheck.platform.hicloud.com/generate_204",
-    interval: 300,
-    tolerance: 50,
-    disable-udp: false,
-    hidden: true,
-    include-all: true,
-  }
-
-# ็ญ–็•ฅ็ป„
-proxy-groups:
-  # ไธป้€‰ๆ‹ฉ็ป„
-  - {
-      name: ๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ,
-      type: select,
-      proxies: [่‡ชๅŠจ้€‰ๆ‹ฉ, ๆ‰‹ๅŠจ้€‰ๆ‹ฉ, DIRECT],
-      url: http://connectivitycheck.platform.hicloud.com/generate_204,
-      icon: https://raw.githubusercontent.com/Orz-3/mini/master/Color/Static.png,
-    }
-
-  # ๆ‰‹ๅŠจ/่‡ชๅŠจ
-  - {
-      name: ๆ‰‹ๅŠจ้€‰ๆ‹ฉ,
-      type: select,
-      proxies:
-        [
-          ๐Ÿ‡ญ๐Ÿ‡ฐ - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ,
-          ๐Ÿ‡ฏ๐Ÿ‡ต - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ,
-          ๐Ÿ‡ฐ๐Ÿ‡ท - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ,
-          ๐Ÿ‡ธ๐Ÿ‡ฌ - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ,
-          ๐Ÿ‡บ๐Ÿ‡ธ - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ,
-          ๐Ÿ‡ฌ๐Ÿ‡ง - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ,
-          ๐Ÿ‡ซ๐Ÿ‡ท - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ,
-          ๐Ÿ‡ฉ๐Ÿ‡ช - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ,
-          ๐Ÿ‡น๐Ÿ‡ผ - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ,
-          Others - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ,
-        ],
-      url: http://connectivitycheck.platform.hicloud.com/generate_204,
-      icon: https://raw.githubusercontent.com/Orz-3/mini/master/Color/Cylink.png,
-    }
-  - {
-      name: ่‡ชๅŠจ้€‰ๆ‹ฉ,
-      type: select,
-      proxies:
-        [
-          ๐Ÿ‡ญ๐Ÿ‡ฐ - ่‡ชๅŠจ้€‰ๆ‹ฉ,
-          ๐Ÿ‡ฏ๐Ÿ‡ต - ่‡ชๅŠจ้€‰ๆ‹ฉ,
-          ๐Ÿ‡ฐ๐Ÿ‡ท - ่‡ชๅŠจ้€‰ๆ‹ฉ,
-          ๐Ÿ‡ธ๐Ÿ‡ฌ - ่‡ชๅŠจ้€‰ๆ‹ฉ,
-          ๐Ÿ‡บ๐Ÿ‡ธ - ่‡ชๅŠจ้€‰ๆ‹ฉ,
-          ๐Ÿ‡ฌ๐Ÿ‡ง - ่‡ชๅŠจ้€‰ๆ‹ฉ,
-          ๐Ÿ‡ซ๐Ÿ‡ท - ่‡ชๅŠจ้€‰ๆ‹ฉ,
-          ๐Ÿ‡ฉ๐Ÿ‡ช - ่‡ชๅŠจ้€‰ๆ‹ฉ,
-          ๐Ÿ‡น๐Ÿ‡ผ - ่‡ชๅŠจ้€‰ๆ‹ฉ,
-        ],
-      url: http://connectivitycheck.platform.hicloud.com/generate_204,
-      icon: https://raw.githubusercontent.com/Orz-3/mini/master/Color/Urltest.png,
-    }
-
-  # ๅบ”็”จๅˆ†็ป„
-  - {
-      name: โœˆ๏ธ ็”ตๆŠฅไฟกๆฏ,
-      type: select,
-      proxies:
-        [
-          ๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ,
-          ๐Ÿ‡ญ๐Ÿ‡ฐ - ่‡ชๅŠจ้€‰ๆ‹ฉ,
-          ๐Ÿ‡ฏ๐Ÿ‡ต - ่‡ชๅŠจ้€‰ๆ‹ฉ,
-          ๐Ÿ‡ธ๐Ÿ‡ฌ - ่‡ชๅŠจ้€‰ๆ‹ฉ,
-          ๐Ÿ‡บ๐Ÿ‡ธ - ่‡ชๅŠจ้€‰ๆ‹ฉ,
-        ],
-      icon: https://raw.githubusercontent.com/Orz-3/mini/master/Color/Telegram.png,
-    }
-  - {
-      name: ๐Ÿค– AIGC,
-      type: select,
-      proxies:
-        [
-          ๐Ÿ‡บ๐Ÿ‡ธ - ่‡ชๅŠจ้€‰ๆ‹ฉ,
-          ๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ,
-          ๐Ÿ‡ญ๐Ÿ‡ฐ - ่‡ชๅŠจ้€‰ๆ‹ฉ,
-          ๐Ÿ‡ฏ๐Ÿ‡ต - ่‡ชๅŠจ้€‰ๆ‹ฉ,
-          ๐Ÿ‡ธ๐Ÿ‡ฌ - ่‡ชๅŠจ้€‰ๆ‹ฉ,
-        ],
-      icon: https://raw.githubusercontent.com/Orz-3/mini/master/Color/OpenAI.png,
-    }
-  - {
-      name: ๐ŸŽ ่‹นๆžœๆœๅŠก,
-      type: select,
-      proxies: [DIRECT, ๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ, ๐Ÿ‡ญ๐Ÿ‡ฐ - ่‡ชๅŠจ้€‰ๆ‹ฉ, ๐Ÿ‡บ๐Ÿ‡ธ - ่‡ชๅŠจ้€‰ๆ‹ฉ],
-      icon: https://raw.githubusercontent.com/Orz-3/mini/master/Color/Apple.png,
-    }
-  - {
-      name: โ“‚๏ธ ๅพฎ่ฝฏๆœๅŠก,
-      type: select,
-      proxies: [DIRECT, ๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ, ๐Ÿ‡ญ๐Ÿ‡ฐ - ่‡ชๅŠจ้€‰ๆ‹ฉ, ๐Ÿ‡บ๐Ÿ‡ธ - ่‡ชๅŠจ้€‰ๆ‹ฉ],
-      icon: https://raw.githubusercontent.com/Orz-3/mini/master/Color/Microsoft.png,
-    }
-
-  # ่‡ชๅŠจ้€‰ๆ‹ฉ - ๆŒ‰ๅœฐๅŒบ
-  - { name: ๐Ÿ‡ญ๐Ÿ‡ฐ - ่‡ชๅŠจ้€‰ๆ‹ฉ, <<: *Auto, filter: *FilterHK }
-  - { name: ๐Ÿ‡ฏ๐Ÿ‡ต - ่‡ชๅŠจ้€‰ๆ‹ฉ, <<: *Auto, filter: *FilterJP }
-  - { name: ๐Ÿ‡ฐ๐Ÿ‡ท - ่‡ชๅŠจ้€‰ๆ‹ฉ, <<: *Auto, filter: *FilterKR }
-  - { name: ๐Ÿ‡ธ๐Ÿ‡ฌ - ่‡ชๅŠจ้€‰ๆ‹ฉ, <<: *Auto, filter: *FilterSG }
-  - { name: ๐Ÿ‡บ๐Ÿ‡ธ - ่‡ชๅŠจ้€‰ๆ‹ฉ, <<: *Auto, filter: *FilterUS }
-  - { name: ๐Ÿ‡ฌ๐Ÿ‡ง - ่‡ชๅŠจ้€‰ๆ‹ฉ, <<: *Auto, filter: *FilterUK }
-  - { name: ๐Ÿ‡ซ๐Ÿ‡ท - ่‡ชๅŠจ้€‰ๆ‹ฉ, <<: *Auto, filter: *FilterFR }
-  - { name: ๐Ÿ‡ฉ๐Ÿ‡ช - ่‡ชๅŠจ้€‰ๆ‹ฉ, <<: *Auto, filter: *FilterDE }
-  - { name: ๐Ÿ‡น๐Ÿ‡ผ - ่‡ชๅŠจ้€‰ๆ‹ฉ, <<: *Auto, filter: *FilterTW }
-
-  # ๆ‰‹ๅŠจ้€‰ๆ‹ฉ - ๆŒ‰ๅœฐๅŒบ
-  - { name: ๐Ÿ‡ญ๐Ÿ‡ฐ - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ, <<: *Select, filter: *FilterHK }
-  - { name: ๐Ÿ‡ฏ๐Ÿ‡ต - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ, <<: *Select, filter: *FilterJP }
-  - { name: ๐Ÿ‡ฐ๐Ÿ‡ท - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ, <<: *Select, filter: *FilterKR }
-  - { name: ๐Ÿ‡ธ๐Ÿ‡ฌ - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ, <<: *Select, filter: *FilterSG }
-  - { name: ๐Ÿ‡บ๐Ÿ‡ธ - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ, <<: *Select, filter: *FilterUS }
-  - { name: ๐Ÿ‡ฌ๐Ÿ‡ง - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ, <<: *Select, filter: *FilterUK }
-  - { name: ๐Ÿ‡ซ๐Ÿ‡ท - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ, <<: *Select, filter: *FilterFR }
-  - { name: ๐Ÿ‡ฉ๐Ÿ‡ช - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ, <<: *Select, filter: *FilterDE }
-  - { name: ๐Ÿ‡น๐Ÿ‡ผ - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ, <<: *Select, filter: *FilterTW }
-  - { name: Others - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ, <<: *Select, filter: *FilterOthers }
-
-  # ๅ…จ้ƒจ่Š‚็‚น
-  - { name: AllIn - ๆ‰‹ๅŠจ้€‰ๆ‹ฉ, <<: *Select, filter: *FilterAll }
-  - { name: AllIn - ่‡ชๅŠจ้€‰ๆ‹ฉ, <<: *Auto, filter: *FilterAll }
-
-### ่ง„ๅˆ™้…็ฝฎ
-RuleSet_classical:
-  &RuleSet_classical {
-    type: http,
-    behavior: classical,
-    interval: 43200,
-    format: text,
-    proxy: ๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ,
-  }
-RuleSet_domain:
-  &RuleSet_domain {
-    type: http,
-    behavior: domain,
-    interval: 43200,
-    format: text,
-    proxy: ๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ,
-  }
-RuleSet_ipcidr:
-  &RuleSet_ipcidr {
-    type: http,
-    behavior: ipcidr,
-    interval: 43200,
-    format: text,
-    proxy: ๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ,
-  }
-
-# ่ฎข้˜…่ง„ๅˆ™
-rule-providers:
-  reject_non_ip_no_drop:
-    <<: *RuleSet_classical
-    url: "https://ruleset.skk.moe/Clash/non_ip/reject-no-drop.txt"
-    path: "./rule_set/sukkaw_ruleset/reject_non_ip_no_drop.txt"
-
-  reject_non_ip_drop:
-    <<: *RuleSet_classical
-    url: https://ruleset.skk.moe/Clash/non_ip/reject-drop.txt
-    path: ./rule_set/sukkaw_ruleset/reject_non_ip_drop.txt
-
-  reject_non_ip:
-    <<: *RuleSet_classical
-    url: https://ruleset.skk.moe/Clash/non_ip/reject.txt
-    path: ./rule_set/sukkaw_ruleset/reject_non_ip.txt
-
-  reject_domainset:
-    <<: *RuleSet_domain
-    url: https://ruleset.skk.moe/Clash/domainset/reject.txt
-    path: ./rule_set/sukkaw_ruleset/reject_domainset.txt
-
-  reject_ip:
-    <<: *RuleSet_classical
-    url: https://ruleset.skk.moe/Clash/ip/reject.txt
-    path: ./rule_set/sukkaw_ruleset/reject_ip.txt
-
-  cdn_domainset:
-    <<: *RuleSet_domain
-    url: https://ruleset.skk.moe/Clash/domainset/cdn.txt
-    path: ./rule_set/sukkaw_ruleset/cdn_domainset.txt
-
-  cdn_non_ip:
-    <<: *RuleSet_domain
-    url: https://ruleset.skk.moe/Clash/non_ip/cdn.txt
-    path: ./rule_set/sukkaw_ruleset/cdn_non_ip.txt
-
-  # ๆ‰€ๆœ‰ๆตๅช’ไฝ“๏ผˆๅŒ…ๆ‹ฌไธŠ่ฟฐๆ‰€ๆœ‰ๆตๅช’ไฝ“๏ผ‰
-  stream_non_ip:
-    <<: *RuleSet_classical
-    url: https://ruleset.skk.moe/Clash/non_ip/stream.txt
-    path: ./rule_set/sukkaw_ruleset/stream_non_ip.txt
-
-  stream_ip:
-    <<: *RuleSet_classical
-    url: https://ruleset.skk.moe/Clash/ip/stream.txt
-    path: ./rule_set/sukkaw_ruleset/stream_ip.txt
-
-  ai_non_ip:
-    <<: *RuleSet_classical
-    url: https://ruleset.skk.moe/Clash/non_ip/ai.txt
-    path: ./rule_set/sukkaw_ruleset/ai_non_ip.txt
-
-  telegram_non_ip:
-    <<: *RuleSet_classical
-    url: https://ruleset.skk.moe/Clash/non_ip/telegram.txt
-    path: ./rule_set/sukkaw_ruleset/telegram_non_ip.txt
-
-  telegram_ip:
-    <<: *RuleSet_classical
-    url: https://ruleset.skk.moe/Clash/ip/telegram.txt
-    path: ./rule_set/sukkaw_ruleset/telegram_ip.txt
-
-  apple_cdn:
-    <<: *RuleSet_domain
-    url: https://ruleset.skk.moe/Clash/domainset/apple_cdn.txt
-    path: ./rule_set/sukkaw_ruleset/apple_cdn.txt
-
-  apple_services:
-    <<: *RuleSet_classical
-    url: https://ruleset.skk.moe/Clash/non_ip/apple_services.txt
-    path: ./rule_set/sukkaw_ruleset/apple_services.txt
-
-  apple_cn_non_ip:
-    <<: *RuleSet_classical
-    url: https://ruleset.skk.moe/Clash/non_ip/apple_cn.txt
-    path: ./rule_set/sukkaw_ruleset/apple_cn_non_ip.txt
-
-  microsoft_cdn_non_ip:
-    <<: *RuleSet_classical
-    url: https://ruleset.skk.moe/Clash/non_ip/microsoft_cdn.txt
-    path: ./rule_set/sukkaw_ruleset/microsoft_cdn_non_ip.txt
-
-  microsoft_non_ip:
-    <<: *RuleSet_classical
-    url: https://ruleset.skk.moe/Clash/non_ip/microsoft.txt
-    path: ./rule_set/sukkaw_ruleset/microsoft_non_ip.txt
-
-  # ่ฝฏไปถๆ›ดๆ–ฐใ€ๆ“ไฝœ็ณป็ปŸ็ญ‰ๅคงๆ–‡ไปถไธ‹่ฝฝ
-  download_domainset:
-    <<: *RuleSet_domain
-    url: https://ruleset.skk.moe/Clash/domainset/download.txt
-    path: ./rule_set/sukkaw_ruleset/download_domainset.txt
-
-  download_non_ip:
-    <<: *RuleSet_domain
-    url: https://ruleset.skk.moe/Clash/non_ip/download.txt
-    path: ./rule_set/sukkaw_ruleset/download_non_ip.txt
-
-  # ๅ†…็ฝ‘ๅŸŸๅๅ’Œๅฑ€ๅŸŸ็ฝ‘ IP
-  lan_non_ip:
-    <<: *RuleSet_classical
-    url: https://ruleset.skk.moe/Clash/non_ip/lan.txt
-    path: ./rule_set/sukkaw_ruleset/lan_non_ip.txt
-
-  lan_ip:
-    <<: *RuleSet_classical
-    url: https://ruleset.skk.moe/Clash/ip/lan.txt
-    path: ./rule_set/sukkaw_ruleset/lan_ip.txt
-
-  domestic_non_ip:
-    <<: *RuleSet_classical
-    url: https://ruleset.skk.moe/Clash/non_ip/domestic.txt
-    path: ./rule_set/sukkaw_ruleset/domestic_non_ip.txt
-
-  direct_non_ip:
-    <<: *RuleSet_classical
-    url: https://ruleset.skk.moe/Clash/non_ip/direct.txt
-    path: ./rule_set/sukkaw_ruleset/direct_non_ip.txt
-
-  global_non_ip:
-    <<: *RuleSet_classical
-    url: https://ruleset.skk.moe/Clash/non_ip/global.txt
-    path: ./rule_set/sukkaw_ruleset/global_non_ip.txt
-
-  domestic_ip:
-    <<: *RuleSet_classical
-    url: https://ruleset.skk.moe/Clash/ip/domestic.txt
-    path: ./rule_set/sukkaw_ruleset/domestic_ip.txt
-
-  china_ip:
-    <<: *RuleSet_ipcidr
-    url: https://ruleset.skk.moe/Clash/ip/china_ip.txt
-    path: ./rule_set/sukkaw_ruleset/china_ip.txt
-
-  my_services:
-    type: inline
-    behavior: classical
-    payload:
-     - DOMAIN-SUFFIX,hpcesia.com
-     - DOMAIN-SUFFIX,trin.one
-     - DOMAIN-SUFFIX,mxrouting.net
-
-# ๅˆ†ๆต่ง„ๅˆ™
-rules:
-  ### ่‡ช่ฎข็ฑป่ง„ๅˆ™
-  - AND,((RULE-SET,my_services),(DST-PORT,80/443)),๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ
-  - RULE-SET,my_services,DIRECT
-
-  ### ้ž IP ็ฑป่ง„ๅˆ™
-  - RULE-SET,reject_non_ip,REJECT
-  - RULE-SET,reject_domainset,REJECT
-  - RULE-SET,reject_non_ip_drop,REJECT-DROP
-  - RULE-SET,reject_non_ip_no_drop,REJECT
-  - RULE-SET,cdn_domainset,๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ
-  - RULE-SET,cdn_non_ip,๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ
-  - RULE-SET,stream_non_ip,๐Ÿ‡บ๐Ÿ‡ธ - ่‡ชๅŠจ้€‰ๆ‹ฉ
-  - RULE-SET,telegram_non_ip,โœˆ๏ธ ็”ตๆŠฅไฟกๆฏ
-  - RULE-SET,apple_cdn,DIRECT
-  - RULE-SET,download_domainset,๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ
-  - RULE-SET,download_non_ip,๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ
-  - RULE-SET,microsoft_cdn_non_ip,DIRECT
-  - RULE-SET,apple_cn_non_ip,DIRECT
-  - RULE-SET,apple_services,๐ŸŽ ่‹นๆžœๆœๅŠก
-  - RULE-SET,microsoft_non_ip,โ“‚๏ธ ๅพฎ่ฝฏๆœๅŠก
-  - RULE-SET,ai_non_ip,๐Ÿค– AIGC
-  - RULE-SET,global_non_ip,๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ
-  - RULE-SET,domestic_non_ip,DIRECT
-  - RULE-SET,direct_non_ip,DIRECT
-  - RULE-SET,lan_non_ip,DIRECT
-
-  ### IP ็ฑป่ง„ๅˆ™
-  - RULE-SET,reject_ip,REJECT
-  - RULE-SET,telegram_ip,โœˆ๏ธ ็”ตๆŠฅไฟกๆฏ
-  - RULE-SET,stream_ip,๐Ÿ‡บ๐Ÿ‡ธ - ่‡ชๅŠจ้€‰ๆ‹ฉ
-  - RULE-SET,lan_ip,DIRECT
-  - RULE-SET,domestic_ip,DIRECT
-  - RULE-SET,china_ip,DIRECT
-  - MATCH,๐ŸŽฏ ่Š‚็‚น้€‰ๆ‹ฉ
modules/nixos/base/mihomo/default.nix
@@ -3,41 +3,12 @@
   config,
   pkgs,
   ...
-}:
-lib.mkIf config.services.mihomo.enable {
-  services.mihomo = {
-    tunMode = true;
-    webui = pkgs.metacubexd;
-    configFile = config.sops.templates."mihomo-config.yaml".path;
+}: {
+  imports = [./config];
+  config = lib.mkIf config.services.mihomo.enable {
+    services.mihomo = {
+      tunMode = true;
+      webui = pkgs.metacubexd;
+    };
   };
-
-  networking.firewall.trustedInterfaces = [
-    "ElysianRealm"
-  ];
-
-  sops.templates."mihomo-config.yaml".content =
-    ''
-      NodeParam:
-        &NodeParam {
-          type: http,
-          interval: 86400,
-          health-check:
-            { enable: true, url: "http://cp.cloudflare.com", interval: 300 },
-        }
-      proxy-providers:
-        Node-YiYuan:
-          url: "${config.sops.placeholder."mihomo/providers/yi_yuan"}"
-          <<: *NodeParam
-          path: "./proxy_provider/providers-yi_yuan.yaml"
-          override:
-            additional-prefix: "[YY]"
-        Node-MoJie:
-          url: "${config.sops.placeholder."mihomo/providers/mo_jie"}"
-          <<: *NodeParam
-          path: "./proxy_provider/providers-mo_jie.yaml"
-          override:
-            additional-prefix: "[MJ]"
-    ''
-    + "\n"
-    + builtins.readFile ./config.yaml;
 }
options/nixos/mihomo.nix
@@ -0,0 +1,35 @@
+{
+  lib,
+  config,
+  pkgs,
+  ...
+}: let
+  inherit (lib) mkOption types;
+  format = pkgs.formats.yaml {};
+  cfg = config.services.mihomo.config;
+in {
+  options.services.mihomo.config = mkOption {
+    default = {};
+    type = types.submodule {
+      freeformType = format.type;
+      options = {
+        tun = {
+          enable = mkOption {
+            default = config.options.services.mihomo.tunMode;
+            type = types.bool;
+          };
+          device = mkOption {
+            default = "utun0";
+            type = types.str;
+          };
+        };
+      };
+    };
+  };
+
+  config = {
+    networking.firewall.trustedInterfaces = lib.mkIf config.services.mihomo.tunMode [cfg.tun.device];
+    sops.templates."mihomo-config.yaml".content = builtins.toJSON cfg;
+    services.mihomo.configFile = config.sops.templates."mihomo-config.yaml".path;
+  };
+}