dsh-web-fetch-fakeip:让 web_fetch 在 Clash TUN + fake-ip 下可用

前言

DeepSeek Harness(DSH)里的 web_fetch 会在直连前解析 hostname,并校验解析结果中的每一个地址都必须是全局可达的公网单播地址;否则抛出 WEB_BLOCKED_URL。在 Clash 或 mihomo 以 TUN 配合 enhanced-mode: fake-ip 运行时,系统 DNS 返回的是 fake-ip 池里的地址(例如 IPv4 默认落在 198.18.0.0/15),这些段在 ipaddr 一类库里会被判为 reserved,校验必然失败。同一台机器上浏览器、curl、web_search 往往仍正常,只有 web_fetch 会挂——因为这套公网地址校验只存在于 @deepseek-ai/dsh-web-fetch-http 这一条链路。

常见变通是改 Clash DNS 为 redir-host、关 TUN 或设代理环境变量。社区插件 dsh-web-fetch-fakeip(维护者 wjj-8283,npm 包 @wjj-8283/dsh-web-fetch-fakeip)走另一条路:不新增 provider、不改 Clash 配置,只在 fake-ip 场景下对保留段做精确放行,其余 SSRF 防护保持不变。

这是什么

dsh-web-fetch-fakeip 是 DSH 的 Cordis 插件,针对 @deepseek-ai/dsh-web-fetch-http(provider id http)的地址解析步骤做可逆补丁。目标很明确:在 TUN + fake-ip 下,web_fetch 不再因「解析到非公网 IP」而整体失败;没有 fake-ip 时插件保持惰性,行为与未安装时一致。

README 中的对比示例:

修复前: Error: URL hostname "mpv.io" resolves to a non-public IP address
修复后: Fetched https://mpv.io/manual/master/ (HTTP 200)

问题从哪来

dsh-web-fetch-http 在解析后会检查每个 entry.address 是否为公网地址,不满足则抛出带 WEB_BLOCKED_URL 的错误。fake-ip 模式下 getaddrinfo 返回的是 TUN 侧造的地址;连接仍可由 Clash 按 fake-ip 反查域名并代连,TLS SNI 仍是原 hostname,但校验发生在连接之前。

另一个细节:解析结果里 IPv4 与 AAAA 可能同时是 fake IP,校验是「结果集里任一地址不合法就整体拒绝」,因此只豁免 IPv4 段不够,IPv6 的 fake-ip 池也要覆盖。

核心功能

插件不新增 fetch provider,也不要求改 DSH 或 Clash 的全局配置。实现上把 HttpFetchProvider 实例上的 resolveAddresses 包一层:

  1. 原逻辑优先——先调用原解析器;正常返回则原样返回。
  2. 仅当原逻辑以 WEB_BLOCKED_URL 拒绝,且重新解析后确认整组地址都落在配置的 fake-ip 保留段内时,才放行该组地址。
  3. 结果中只要有一个地址不属于 fake-ip 段(真实公网 IP、内网、169.254.169.254、::1、Tailscale CGNAT 100.64.0.0/10 等),仍按原逻辑拒绝。

默认豁免的 CIDR(均为公网上不应作为真实目的地使用的保留段,与 Clash / mihomo / Clash Verge 常见默认一致):

段 说明
198.18.0.0/15 RFC 2544;Clash / mihomo 默认 fake-ip IPv4 范围
fdfe:dcba:9876::/64 Clash Verge 常见 fake-ip-range6
2001:2::/48 RFC 5180;与 Verge 另一处 IPv6 fake-ip 配置对应

禁用插件或重载后,被包裹的 provider 会恢复原行为(若期间其他代码替换了 resolveAddresses,则不回滚,避免覆盖他人补丁)。

GUI 侧会在「设置」导航中增加 fake-ip 直连修复 项,可开关插件并编辑地址段列表;读写落在当前 profile 的 Cordis patch,服务端可热加载,不必为改配置单独重启(安装/卸载插件本身 README 仍要求重启 dsh)。

安装与启用

将 <profile> 换成你实际使用的 DSH profile 名称。插件以当前 dsh 进程权限运行,安装前建议自行查看 GitHub 仓库 源码与 MIT 许可证。

从 npm 安装(推荐)

dsh plugin --profile <profile> add @wjj-8283/dsh-web-fetch-fakeip

装完后重启 dsh。

从 GitHub 安装

dsh plugin --profile <profile> add github:wjj-8283/dsh-web-fetch-fakeip-plugin

装完后重启 dsh。

若需本地调试,可克隆仓库后用 link: 路径安装(README 方式 C);日常使用者以上两种 add 即可。

可选配置

在 GUI 的 fake-ip 直连修复 中可改 enabled 与各 CIDR 行;也可直接编辑 profile 的 patch 层,例如 $DSH_HOME/profiles/<profile>/cordis.patch.yml:

- id: web-fetch-fakeip
  config:
    enabled: true
    fakeIpRanges:
      - 198.18.0.0/15
      - fdfe:dcba:9876::/64
      - 2001:2::/48

enabled: false 可暂停插件而无需卸载。非法 CIDR 会记错误日志并回落到默认段,避免一次手误导致插件 entry 加载失败、设置页也无法打开。

典型用法与验证

安装并重启 dsh 后,在仍使用 TUN + fake-ip 的 Clash / mihomo 环境下,对先前会报 non-public IP address 的 URL 再次调用 web_fetch,应能正常返回 HTTP 200 与正文。README 用 https://mpv.io/manual/master/ 作为修复前后对照;你本地可用任意此前被拦的外链复测。

同时可确认 SSRF 相关地址仍被拒绝(README 截图说明 loopback 与云元数据地址在修复后仍会被拒),说明豁免范围限定在 fake-ip 保留段。

适用场景与注意

适合谁: 本机长期开 Clash / mihomo TUN + fake-ip,且希望 DSH 智能体里的 web_fetch 与浏览器一样能拉取公网页面,又不想为 DSH 单独改 DNS 模式、关 TUN 或堆代理环境变量。

已知边界(来自 README):

  • 只补丁 http 这一条 web_fetch provider;上游若改掉 resolveAddresses 注入点,插件可能静默失效(启动日志会显示「已接管 0 个」)。
  • 判定保守:一组解析结果中混入任一非 fake-ip 地址则维持拒绝;正常 fake-ip 部署下通常不会出现混合结果。
  • fake-ip 段内地址若被公网服务实际使用会被一并放行;RFC 2544 / RFC 5180 相关段在实践中不会作为公网目的地。
  • 运行时依赖 Node 内置的 node:net BlockList 做 CIDR 匹配;package.json 要求 Node >=22.19。

卸载: 临时停用可在 patch 里设 enabled: false。彻底移除 npm / GitHub 安装的包:

dsh plugin --profile <profile> remove @wjj-8283/dsh-web-fetch-fakeip

无论停用还是卸载,README 均要求重启 dsh。

结尾

dsh-web-fetch-fakeip 解决的是 DSH 在 Clash TUN + fake-ip 下 web_fetch 与系统 DNS 行为不一致的问题:用最小、可逆的解析层补丁,只放行 fake-ip 保留段,不削弱对内网与元数据地址的防护。插件属于 DSH 社区生态(目录站点与 DeepSeek / 幻方无官方从属关系),可按需从社区目录或 GitHub 获取。

  • 目录页:https://www.skillhub.cn/plugins/wjj-8283/dsh-web-fetch-fakeip-plugin
  • GitHub:https://github.com/wjj-8283/dsh-web-fetch-fakeip-plugin
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜