DEV Community

amoorzheyu
amoorzheyu

Posted on

系统代理配置不可持久化的问题排查与解决

最近在使用 Mihomo(Clash 内核) 时,我遇到了一个非常具体、但又绕不开的实际问题:
我需要在开启系统代理的同时,正常访问公司内网的域名,而系统代理这一层恰好出了问题,并且在这个软件里无法配置。

这篇文章记录的不是网络原理本身,而是系统代理配置在现实使用场景中被覆盖、无法持久化时,应该如何工程化地解决,以及最终我为什么选择用一个 bat 脚本来兜底。


一、真实的使用场景:系统代理 + 内网域名访问

先说清楚背景动机。

我的使用场景是:

  • 浏览器需要使用系统代理(由 Mihomo 提供)
  • 同时需要访问公司内网网站
  • 内网网站是通过 内网域名 访问的
  • 这些域名依赖:

    • 系统路由
    • 内网 DNS
  • 不能走代理

在 Windows 下,浏览器是否走代理,完全由 系统代理配置 决定,尤其是:

  • “不使用代理的地址”(ProxyOverride)

只要内网域名没有被正确配置在这里:

  • 浏览器请求就会被交给代理程序
  • 解析和连接都会走错路径
  • 结果就是内网网站无法访问

二、问题出现:系统代理例外配置无法保持

一开始的操作非常直觉:

  • 打开 Windows 系统代理设置
  • 在“不使用代理的地址”里添加:

    • 内网网段
    • 内网域名
  • 保存

当下效果是完全正确的:

  • 内网域名立刻可以访问
  • 行为符合预期

但问题在于:

  • 关闭 Mihomo
  • 再重新启动
  • 刚刚添加的系统代理例外全部消失

而且这是一个稳定可复现的现象。

这说明问题已经不在“配置是否正确”,而在于:

有程序在启动时主动覆盖了系统代理配置。


三、确认事实:Mihomo 启动会重写系统代理

通过简单的验证可以确认:

  • 在 Mihomo 未运行时修改系统代理
  • 注册表中 ProxyOverride 已正确更新
  • 启动 Mihomo
  • 对应配置被整体重写

这意味着:

  • Mihomo 在启动时
  • 并不是“读取并合并”现有系统代理配置
  • 而是直接写入一套固定模板

这也是为什么:

  • 手动改 UI 没有持久性
  • 重启软件就会丢失配置

四、为什么这个问题在 Mihomo 里无法解决

接下来一个很自然的想法是:
能不能在 Mihomo 里直接配置这些系统代理例外?

结论是:不能。

原因在于设计取向:

  • Mihomo 关注的是:

    • 代理端口
    • 规则匹配
    • 代理侧 DNS
  • Windows 系统代理对它来说只是:

    • 一个“启动时顺手写一次”的配置

系统代理例外(ProxyOverride)并不是它希望用户长期维护的配置项。

换句话说:

系统代理配置只是 Mihomo 的副作用,而不是它的核心能力。


五、关键认知转变:UI 不是最终真相

到这里,一个关键认知就很清楚了:

  • Windows 的系统代理设置页面只是一个 UI
  • 真正决定行为的是注册表

所有系统代理相关内容最终都落在:

HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings
Enter fullscreen mode Exit fullscreen mode

其中关键字段是:

  • ProxyOverride

在这个模型下:

谁最后写入,谁就拥有最终控制权。

而在我的场景中:

  • Mihomo 每次启动都会成为“最后写入者”

六、思路转变:不阻止覆盖,而是在覆盖后修正

确认这些事实之后,解决思路反而变简单了:

  • 不试图阻止 Mihomo 写系统代理
  • 不反复通过 UI 去“抢配置”
  • 而是:

接受覆盖的存在,在覆盖完成之后,把配置修正回来。

这是一个典型的工程问题,而不是配置技巧问题。


七、最终方案:用 bat 脚本维护 ProxyOverride

系统代理例外本质上只是一个字符串:

  • 分号分隔
  • 支持通配符
  • 支持内网域名
  • 支持 <local>

非常适合脚本化维护。

脚本的目标只有一个:

无论当前系统代理被写成什么样,都把 ProxyOverride 改成我期望的状态。

使用方式

  • 启动 Mihomo
  • 执行一次脚本
  • 系统代理例外立即恢复

八、最终使用的 bat 脚本

下面是我最终使用的脚本内容,逻辑尽量保持简单和稳定。

@echo off

REM =========================
REM ProxyOverride 脚本
REM =========================

set LOCAL_BASIC=localhost;127.*
set PRIVATE_NETS=10.*;192.168.*
set PRIVATE_172=172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*

REM 注意:<local> 不能进 set 变量
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyOverride /t REG_SZ /d "%LOCAL_BASIC%;%PRIVATE_NETS%;%PRIVATE_172%;*.suanleme.local;<local>" /f

ie4uinit.exe -show

echo.
echo Current ProxyOverride:
reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyOverride
echo.
Enter fullscreen mode Exit fullscreen mode

这个脚本的特点是:

  • 不依赖 UI
  • 不依赖 Mihomo 是否支持配置
  • 每次执行结果确定
  • 可随时修改、扩展内网规则

九、最终效果

使用脚本后,流程变成:

  1. 启动 Mihomo
  2. 系统代理被写入其默认配置
  3. 执行脚本
  4. 内网域名被正确排除出系统代理

结果是:

  • 内网网站访问稳定
  • 不再反复检查系统代理 UI
  • 不再担心“下次启动又坏了”

十、总结

这次问题表面上是:

“系统代理配置为什么保存不了?”

但真正学到的是:

  • 当配置反复被覆盖时,说明你找错了修改入口
  • UI 只是表象,注册表才是底层事实
  • 当工具不支持你的需求粒度时:

    • 与其反复手工操作
    • 不如用脚本补齐能力

最终我接受了一个很工程化的结论:

当配置开始变得不可控时,
脚本不是折腾,而是最稳妥的解决方案。

把这次过程记录下来,避免以后再从同一个坑重新踩一遍。

Top comments (0)