🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI
广告☁️ 云服务器特惠阿里云首购 8 折 · 腾讯云合作特惠
DeepSeek Harness Hub
← 返回列表

1499501762/dsh-web-fetch-proxy

DeepSeek Harnessspec-screened扫描:中风险在 GitHub 查看 ↗
⚠ 装前注意

DSH 插件:让内置 webfetch 经由本地代理出网,绕过 TUN 模式下 fake-ip 假地址被 SSRF…

基本兼容但装前注意:未发布到 npm registry,仅可从源码安装 · 最近上游提交 2026/9/17 · 已提供中文文档

DSH 插件:将内置的 web_fetch 通过本地代理路由,这样 TUN fake-ip 地址就不会再触发 SSRF 防护。

综合分
35.4
GitHub 分
35.4
用户评分
—
★ Stars
1
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add 1499501762/dsh-web-fetch-proxy
未发布到 npm registry,仅可从源码安装,改用 GitHub 源安装
信任档位:已验证本站已于 4 天前真实安装成功(L4 · 真实安装)
是什么
dsh 原生插件 · tool
装得上吗
本站已真实安装成功(L4 · 真实安装,非静态推断)
安全吗
本站尚未对该插件做风险分级(暂未覆盖,不等同于无风险)
还在维护吗
活跃:最近一次提交在 8 天前

档位由下列信号合成:本站实装验证(真实安装,当前最高到 L4)· 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。下方各区块是它的证据明细。 验证判据与等级说明 →

🟢实装验证通过· 2026/9/22
由本站实装验证器在真实 dsh 环境安装成功,非静态推断。
数据截至 2026/9/20(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
安装兼容性检查⚠ 装前注意

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包dsh-web-fetch-proxy(未发布到 npm,仅可源码安装)
✓Node 引擎要求 >=20.18.1 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

未发布到 npm registry,仅可从源码安装

验证方式:npm registry 存在性 + package.json 静态校验 · 最后验证 2026/9/20 20:43:07

依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-http-proxy@deepseek-ai/dsh-launch-environment@deepseek-ai/schemastery
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动

README

由 DeepSeek 最新模型翻译生成
dsh-web-fetch-proxy

DSH 插件:让内置 web_fetch 经由本地代理出网,绕过 TUN 模式下 fake-ip 假地址被 SSRF 防护拦截的问题。

license

症状

在开着 TUN 模式代理(Clash Verge / Mihomo、sing-box、Surge 等)的 Windows 上,DSH 的 web_fetch 对所有域名都失败,
报错形如:

https://raw.githubusercontent.com/... -> ERROR URL hostname "raw.githubusercontent.com" resolves to a non-public IP address

关键点是:DNS 解析成功了。失败的原因不是解析不了,而是解析出来的地址被判定为非公网地址从而被主动拦截。

根因

1. TUN + fake-ip 会返回假地址

Clash Verge Rev 的运行时配置(%APPDATA%\io.github.clash-verge-rev.clash-verge-rev\config.yaml)里:

mixed-port: 7897
tun:
enable: true
dns-hijack: [any:53]

而它的 DNS 覆盖层设置了 fake-ip:

dns:
enable: true
enhanced-mode: fake-ip
fake-ip-range: 28.0.0.1/8
fake-ip-range6: fdfe:dcba:9876::1/64

于是系统 DNS 被 53 端口劫持后,任何域名都会得到伪造地址:

raw.githubusercontent.com  A     28.0.0.250
raw.githubusercontent.com  AAAA  fdfe:dcba:9876::ed
DNS 服务器地址:                  fdfe:dcba:9876::2

这是 fake-ip 模式的正常行为:故意返回假 IP,才能在 TLS 之前按域名分流。

2. web_fetch 的 SSRF 防护会拒绝这类地址

@deepseek-ai/dsh-web-fetch-http 在建立连接之前先自己解析域名,并逐条校验:

// node_modules/@deepseek-ai/dsh-web-fetch-http/lib/index.js
const resolved = await resolver(hostname, { all: true, order: "verbatim" });
for (const entry of resolved) {
if (!isPublicIpAddress(entry.address))
throw new WebError(URL hostname "${hostname}" resolves to a non-public IP address, "WEB_BLOCKED_URL");
}

isPublicIpAddress 用 ipaddr.js 判定,实测结果:

28.0.0.250           ipv4  unicast      通过
fdfe:dcba:9876::ed   ipv6  uniqueLocal  拒绝

从 GitHub 安装

dsh plugin --profile web add github:1499501762/dsh-web-fetch-proxy

安装后重启 DSH。启动日志里出现下面这行就说明生效了:

[web-fetch-proxy] web_fetch now tunnels through http://127.0.0.1:7897 (source: clash-config:...); the local DNS check is bypassed.

注意:本插件的 cordis.patch.yml 已经声明了插入行,dsh plugin add 会把它写进 profile 的 bundles。
如果你的 profile 是手动维护的,也可以自己在 /profiles/web/cordis.patch.yml 里加:

- insert:
- id: web-fetch-proxy
name: dsh-web-fetch-proxy

配置页面

重启 DSH 后,设置 → 常规 里会出现「Web Fetch 代理」一栏:

| 控件 | 作用 |
| --- | --- |
| 自动检测 / 手动代理 / 关闭 | 写 web-fetch-proxy settings 命名空间的 proxy 字段,立即生效,无需重启 |
| 代理地址输入框 | 手动模式下填 http://127.0.0.1:7897 或 127.0.0.1:7897;主机端会校验,非法地址在保存前就被拒绝 |
| 绕过列表 | 追加 noProxy 条目;localhost、127.0.0.1、::1 由 dsh-http-proxy 强制绕过 |
| 状态行 / 重新检测 | 读宿主实时状态(当前路由、来源、失败原因),并可按需重新探测一次 |

状态行显示的是宿主真正生效的结果,例如:

已生效  http://127.0.0.1:7897  (via: clash-config:C:\Users\...\config.yaml)

页面读的是一个带围栏的只读接口 POST /web-fetch-proxy/api(仅接受 loopback / 受信 Host、同源请求):
请求体 {"action":"status"} 取状态,{"action":"redetect"} 触发一次重新探测。

页面不需要「重启后生效」:设置走的是 applies: live 的 settings 命名空间,改动通过
scope.watch() 直接驱动路由重建(旧的策略先释放,再按新配置重新探测安装)。

配置(cordis 层)

页面写的是同一份配置;cordis.patch.yml 的 config 提供部署级基线与默认值(settings 的 base 层),
页面上没有暴露的字段只能在这里改:

- insert:
- id: web-fetch-proxy
name: dsh-web-fetch-proxy
config:
enabled: true        # false 则完全不介入
proxy: auto          # auto | off | http://host:port | host:port
noProxy: ""          # 额外的不走代理的域名,逗号分隔
retryMs: 15000       # 自动发现失败后的重试间隔,0 = 不重试
maxRetries: 20       # 最大重试次数
probeTimeoutMs: 400  # 单个候选代理的 TCP 探测超时

| 字段 | 类型 | 默认 | 说明 |
| --- | --- | --- | --- |
| enabled | boolean | true | 部署级总开关;false 时插件不安装任何路由(页面无法覆盖) |
| proxy | string | auto | auto 自动发现;off/none/direct 不安装;也可以写死代理地址。页面可改 |
| noProxy | string | "" | 追加到绕过列表(localhost、127.0.0.1、::1 由 dsh-http-proxy 强制绕过)。页面可改 |
| retryMs | number | 15000 | 代理客户端比 DSH 晚启动时,按此间隔重试 |
| maxRetries | number | 20 | 重试上限(约 5 分钟) |
| probeTimeoutMs | number | 400 | 候选代理的 TCP 连接超时 |

也可以直接用环境变量指定,优先级高于自动发现:

set DSH_WEB_FETCH_PROXY=http://127.0.0.1:7897

代理发现顺序

proxy: auto 时按以下顺序找第一个当前能建立 TCP 连接的候选:

1. DSH_WEB_FETCH_PROXY 环境变量;
2. HTTPS_PROXY / https_proxy / HTTP_PROXY / http_proxy / ALL_PROXY / all_proxy;
3. 本地 Clash / Mihomo / Clash Verge 配置里的 mixed-port
(%APPDATA%\io.github.clash-verge-rev.clash-verge-rev\config.yaml 等 8 个已知路径);
4. Windows WinINET 系统代理(HKCU\...\Internet Settings,即系统代理开关打开时的设置);
5. 常见端口 TCP 探测:7897、7890、7891、7899、10809、10808、1080、2080、20171、8889。

任何候选都必须先通过 TCP 探测,避免把路由指向一个没在运行的代理。

与 dsh-network-proxy 的关系
dsh-network-proxy 管的是全局 undici Dispatcher(跟随系统 / 手动 / 直连),它能让普通 fetch 走代理,
但它没有触及 @deepseek-ai/dsh-http-proxy 的策略,所以 web_fetch 不受其影响。

两者不冲突。 把两个插件装进同一个进程实测的结果:

| 场景 | proxyRouteFor() | web_fetch |
| --- | --- | --- |
| 只装 dsh-network-proxy(直连模式) | DIRECT | 失败 WEB_BLOCKED_URL |
| 再挂上本插件 | PROXIED 127.0.0.1:7897 | 200 |
| dsh-network-proxy 经 settings 切到「手动」 | PROXIED | 200 |
| dsh-network-proxy 切到「直连」(清空 HTTP(S)_PROXY) | PROXIED | 200 |
| 连续来回切换三次 | PROXIED | 每次都是 200 |

要点:

- web_fetch 只认 dsh-http-proxy 自己持有的策略与 dispatcher,别的插件 setGlobalDispatcher() 改不动它
——实测 dsh-network-proxy 把 HTTPS_PROXY 清空后,web_fetch 照样走隧道;
- 两者确实共用 undici 全局 Dispatcher(后写者赢),但这只影响普通 fetch()(模型 API、其它插件),不影响 web_fetch;
- 两者都只关闭自己创建的 dispatcher,所以反复切换模式不会把对方弄坏;
- 唯一会让人困惑的是:dsh-network-proxy 的「直连 / 手动 / 跟随系统」不管辖 web_fetch。
若把它设为「直连」,普通请求直连而 web_fetch 仍走代理,界面上会显得不一致。要让两条路径一致,
就把它们指向同一个代理,或在本插件的 config.proxy 里写死同一个地址。

安全性

- fail-open:模块求值期不抛错,apply() 不抛错,异步流程只在 logger 里报告失败;
- 不覆盖宿主已有的代理路由(启动时若 proxyRouteFor() 已经是 proxied,直接退出);
- 只使用 node: 内置模块做静态导入,宿主包全部用动态 import() 包在 try/catch 里,
即使某个 DSH 版本改了内部结构,也不会阻止宿主启动;
- 安装后会用 proxyRouteFor() 自检,不生效就回滚。

为什么需要「锚定解析」

插件通常以 link: 方式从 harness 目录树之外安装,此时它的真实路径在 profiles/ 之外,
裸 import("@deepseek-ai/dsh-http-proxy") 会 ERR_MODULE_NOT_FOUND。
本插件会按 DSH_HOME、app 安装目录、cwd 依次构造解析锚点,用 createRequire(anchor).resolve() 定位宿主包。
Node 的 ES 模块按 realpath 去重,因此通过锚点拿到的实例与 dsh-web-fetch-http 内部用的是同一个模块实例
(bare === anchored === junction === appCopy 的恒等性已验证)。

验证

npm test            # 30 个单元 / 集成测试
npm run verify      # 对真实网址做前后对照,打印 route 与 HTTP 状态码
npm run verify -- https://example.com/

测试覆盖:代理发现、宿主模块锚定解析、路由生命周期(含「慢探测不覆盖新配置」的代际保护)、
surfaces(settings 命名空间注册、状态接口围栏与方法校验、设置改动实时重建路由)、
以及真实 HttpFetchProvider 的前后对照集成测试。

npm run verify 会在独立进程里跑真实的 HttpFetchProvider,安装前后各取一次,
不改动正在运行的 DSH。

目录结构

dsh-web-fetch-proxy/
├── lib/index.js          # cordis 宿主插件:apply / settings 命名空间 / 状态接口
├── lib/manager.js        # 路由生命周期:安装、释放、代际保护、重试、状态
├── lib/client.js         # 设置页(设置 → 常规 的「Web Fetch 代理」一栏)
├── lib/detect.js         # 代理发现(环境变量 / Clash 配置 / 系统代理 / 端口探测)
├── lib/harness.js        # 宿主模块的锚定解析与 launch environment 构造
├── scripts/verify.mjs    # 真实网络的前后对照验证脚本
├── test/                 # node:test 测试(detect / harness / manager / surfaces / integration)
├── cordis.patch.yml      # 插件注入声明
└── package.json          # 含 dsh.client 声明,宿主据此加载设置页

常见问题

Q: 装完之后 web_fetch 还是失败?

A: 看启动日志。如果是 no reachable local proxy found,说明插件没找到代理:确认代理客户端已启动并监听
(Clash Verge 默认 mixed-port: 7897),或者用 DSH_WEB_FETCH_PROXY 显式指定。
如果是 cannot reach the harness network modules,说明 DSH 版本差异导致内部包路径变了,欢迎提 issue。

Q: 会不会影响模型 API 的请求?

A: 进程级策略会对所有出站 HTTP 生效,模型 API 的流量也会经过本地代理,由代理客户端按自己的规则分流。
如果你希望某些域名直连,用 noProxy 或代理客户端的规则处理。

Q: 关掉代理客户端后 DSH 会断网吗?

A: 不会。插件只在探测到代理可连接时才安装路由;代理中途退出属于运行期变化,
此时出站请求会失败,重启 DSH 或重新触发(插件会重试)即可恢复直连。
问:在设置页改了模式,需要重启吗?

答:不需要。设置写入的是 applies: live 的 settings 命名空间,宿主端 scope.watch() 收到后会立即重建路由;
状态行会在一两秒内刷新出新结果。重启只影响插件本身更新(例如升级版本后加载新的客户端代码)。

问:状态行一直显示「未找到可用的本地代理」?

答:说明候选都没通过 TCP 探测。确认代理客户端在运行(Clash Verge 默认 mixed-port 7897),
或在页面上切到「手动代理」直接填地址;也可以点「重新检测」强制重探一次。

问:设置页没有出现?

答:该页面要求宿主端注册了 web-fetch-proxy 这个 settings 命名空间,否则整行会隐藏。
可能是 @deepseek-ai/schemastery 锚定解析失败(日志里会有提示),或插件没被加载。

问:支持 SOCKS 代理吗?

答:不支持。dsh-http-proxy 只接受 http(s)://,本插件与之保持一致;Clash 的 mixed-port 本身就是 HTTP 混合端口。

许可证

MIT © 2026 Tong317

上游仓库有新提交时邮件通知你(每天最多一封,无更新不打扰),随时一键退订。

同作者(1499501762)的其他插件

💬 加入社群

插件用法、部署报错、新插件第一时间同步——群里问,比一个人翻文档快。

DPharness QQ 群二维码,QQ 扫码进群
QQ 扫码进群
DPharness 飞书群二维码,飞书扫码进群
飞书扫码进群