fix: keep OneDrive on direct routing
CI / lite (pull_request) Successful in 3s

This commit is contained in:
2026-08-30 16:00:41 +08:00
parent f05bffd587
commit 7cfdc0fbcc
6 changed files with 45 additions and 2 deletions
+3 -1
View File
@@ -20,7 +20,7 @@ vpn-rules/
## 为什么需要它 ## 为什么需要它
- 香港代理节点有流量配额(如 BygCloud 100GiB 用满),国内站点/内网流量被隧道进代理会白白烧配额。 - 香港代理节点有流量配额(如 BygCloud 100GiB 用满),国内站点/内网流量被隧道进代理会白白烧配额。
- 必须直连的对象:FRP 控制面(mTLS)、B 站全系、DeepSeek/MiniMax 等国内 LLM API、 - 必须直连的对象:Windows OneDrive 客户端、FRP 控制面(mTLS)、B 站全系、DeepSeek/MiniMax 等国内 LLM API、
内网/私有 IP 段、国区 iCloud、UGREEN 绿联 NAS 云。 内网/私有 IP 段、国区 iCloud、UGREEN 绿联 NAS 云。
- **踩坑**:Clash Verge 全局 `Merge.yaml` 的 `prepend-rules` 会被内核忽略(不生效), - **踩坑**:Clash Verge 全局 `Merge.yaml` 的 `prepend-rules` 会被内核忽略(不生效),
全局直连规则的唯一正确机制是 `profiles/Script.js`(`main(config)` 把规则 prepend 进 `config.rules`)。 全局直连规则的唯一正确机制是 `profiles/Script.js`(`main(config)` 把规则 prepend 进 `config.rules`)。
@@ -36,6 +36,8 @@ python3 scripts/gen_clash_verge_script.py
``` ```
对当前及以后新增/切换的所有订阅生效;订阅更新不会覆盖它。 对当前及以后新增/切换的所有订阅生效;订阅更新不会覆盖它。
脚本还会把国内可达的阿里 DNS 和腾讯 DNS DoH 端点补入 `dns.fallback`,避免境外域名
命中 `DIRECT` 后因供应商的境外 DNS fallback 不可达而解析失败。
Windows 默认写入 `%APPDATA%\io.github.clash-verge-rev.clash-verge-rev\profiles\Script.js`; Windows 默认写入 `%APPDATA%\io.github.clash-verge-rev.clash-verge-rev\profiles\Script.js`;
macOS 默认写入 `~/Library/Application Support/io.github.clash-verge-rev.clash-verge-rev/profiles/Script.js`。 macOS 默认写入 `~/Library/Application Support/io.github.clash-verge-rev.clash-verge-rev/profiles/Script.js`。
+3
View File
@@ -20,6 +20,9 @@
# 路由器端则等 rule-provider 的 interval 到期或手动 reload。 # 路由器端则等 rule-provider 的 interval 到期或手动 reload。
payload: payload:
# Windows OneDrive 客户端始终直连,避免被供应商 Microsoft 规则送入代理
- PROCESS-NAME,OneDrive.exe
# FRP 控制面(mTLS)保持直连 # FRP 控制面(mTLS)保持直连
- DOMAIN,frp.puyuanfh.cn - DOMAIN,frp.puyuanfh.cn
- IP-CIDR,8.133.177.3/32,no-resolve - IP-CIDR,8.133.177.3/32,no-resolve
+1
View File
@@ -1,3 +1,4 @@
PROCESS-NAME,OneDrive.exe
DOMAIN,frp.puyuanfh.cn DOMAIN,frp.puyuanfh.cn
IP-CIDR,8.133.177.3/32,no-resolve IP-CIDR,8.133.177.3/32,no-resolve
DOMAIN-SUFFIX,bilibili.com DOMAIN-SUFFIX,bilibili.com
+1
View File
@@ -11,6 +11,7 @@
# 内网源:http://192.168.50.2:3000/ageorge156/vpn-rules/raw/branch/main/direct.yaml # 内网源:http://192.168.50.2:3000/ageorge156/vpn-rules/raw/branch/main/direct.yaml
rules: rules:
- PROCESS-NAME,OneDrive.exe,DIRECT
- DOMAIN,frp.puyuanfh.cn,DIRECT - DOMAIN,frp.puyuanfh.cn,DIRECT
- IP-CIDR,8.133.177.3/32,DIRECT,no-resolve - IP-CIDR,8.133.177.3/32,DIRECT,no-resolve
- DOMAIN-SUFFIX,bilibili.com,DIRECT - DOMAIN-SUFFIX,bilibili.com,DIRECT
+19 -1
View File
@@ -62,19 +62,37 @@ def render_script(payload: list[str]) -> str:
rules = [f" {to_rule(e)!r}," for e in payload] rules = [f" {to_rule(e)!r}," for e in payload]
lines = "\n".join(rules) lines = "\n".join(rules)
return f"""// 由 vpn-rules/direct.yaml 生成 — 勿手改,改真源后重跑 gen_clash_verge_script.py。 return f"""// 由 vpn-rules/direct.yaml 生成 — 勿手改,改真源后重跑 gen_clash_verge_script.py。
// 全局直连规则:FRP 控制面、B站、国内 LLM、内网段、国区 iCloud、UGREEN 一律 DIRECT。 // 全局直连规则:OneDrive、FRP 控制面、B站、国内 LLM、内网段、国区 iCloud、UGREEN 一律 DIRECT。
const prependRules = [ const prependRules = [
{lines} {lines}
]; ];
// 国内可达的 DoH 同时作为 fallback,确保 OneDrive 等境外域名在 DIRECT 出站前可解析。
const directDnsFallbacks = [
'https://dns.alidns.com/dns-query',
'https://doh.pub/dns-query',
];
function main(config, profileName) {{ function main(config, profileName) {{
const existingRules = Array.isArray(config.rules) ? config.rules : []; const existingRules = Array.isArray(config.rules) ? config.rules : [];
const existingRuleSet = new Set(existingRules); const existingRuleSet = new Set(existingRules);
const dns = config.dns && typeof config.dns === 'object' && !Array.isArray(config.dns)
? config.dns
: {{}};
const existingFallbacks = Array.isArray(dns.fallback)
? dns.fallback
: (typeof dns.fallback === 'string' ? [dns.fallback] : []);
const existingFallbackSet = new Set(existingFallbacks);
config.rules = [ config.rules = [
...prependRules.filter((rule) => !existingRuleSet.has(rule)), ...prependRules.filter((rule) => !existingRuleSet.has(rule)),
...existingRules, ...existingRules,
]; ];
dns.fallback = [
...directDnsFallbacks.filter((server) => !existingFallbackSet.has(server)),
...existingFallbacks,
];
config.dns = dns;
return config; return config;
}} }}
+18
View File
@@ -16,6 +16,7 @@ sys.path.insert(0, str(ROOT / "scripts"))
from gen_clash_verge_script import ( # noqa: E402 from gen_clash_verge_script import ( # noqa: E402
default_output_path, default_output_path,
load_payload, load_payload,
render_script,
to_rule, to_rule,
) )
@@ -193,6 +194,23 @@ class ModuleSpecTests(unittest.TestCase):
) )
self.assertTrue(all(",DIRECT" not in entry for entry in payload)) self.assertTrue(all(",DIRECT" not in entry for entry in payload))
def test_onedrive_process_is_forced_to_use_direct_routing(self) -> None:
payload = load_payload(ROOT / "direct.yaml")
self.assertIn("PROCESS-NAME,OneDrive.exe", payload)
self.assertEqual(
to_rule("PROCESS-NAME,OneDrive.exe"),
"PROCESS-NAME,OneDrive.exe,DIRECT",
)
def test_clash_verge_script_adds_reachable_direct_dns_fallbacks(self) -> None:
script = render_script(["PROCESS-NAME,OneDrive.exe"])
self.assertIn("const directDnsFallbacks", script)
self.assertIn("https://dns.alidns.com/dns-query", script)
self.assertIn("https://doh.pub/dns-query", script)
self.assertIn("config.dns = dns", script)
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()