dsh-proxy-switch:让 DSH 的 web_fetch 在代理环境下正常抓网页

前言

DSH 的 web_fetch 在直连环境里工作正常,但一旦开着 Clash、Surge、v2rayN 这类软件,抓取就很容易失败。排查下来通常是两类问题:TUN 模式把域名解析成 198.18.x.x 这样的假地址,直连安全检查直接拒绝;或者只开了「系统代理」、没开 TUN,DSH 不读系统代理,需要代理的网站打不开。把 HTTP_PROXY 写死进 ~/.dsh/.env 确实能连上,可代理一关,模型对话也跟着断。

下面介绍 dsh-proxy-switch,它就是为这种场景写的插件。

这是什么

  • 维护者:lightrivers
  • 包名:@lightrivers/dsh-proxy-switch,版本 0.4.4,许可证 MIT
  • GitHub:https://github.com/lightrivers/dsh-proxy-switch
  • 目录页:https://www.skillhub.cn/plugins/lightrivers/dsh-proxy-switch,分类「联网工具」,目录页标注星标 0

一句话定位:自动找到本机 HTTP 代理,代理开着时让 web_fetch 走代理,代理关掉后自动改直连,给 web_fetch 单独开一条可切换的线路。默认作用范围是「仅 web_fetch」,不修改全局网络设置、进程环境变量和子进程环境,模型对话和其它工具不受影响。

它解决什么问题

README 列出的适用情况:

  • web_fetch 报 non-public IP address,或域名被解析到 198.18.x.x
  • 代理开了 TUN / 增强模式 / fake-IP,web_fetch 失败
  • 只开了系统代理、没开 TUN,DSH 读不到系统代理,打不开需要代理的网站
  • 写死 HTTP_PROXY 后代理一关,连模型对话都断了
  • 每次开关代理都要手动改配置

原因是 TUN 模式会把域名解析到 198.18.0.0/15 段的假地址,web_fetch 直连时的安全检查不允许访问内网地址;而一旦代理地址写死,代理关闭后什么都连不上。插件在这两条路径之外给 web_fetch 一条可切换的线路。

需要说明的是,README 明确指出:DeepSeek Harness 0.2.2 起,web_fetch 不再拒绝 fake-IP 和内网地址,只用 TUN 的话新版不装插件也能抓网页。插件仍然适合只开系统代理的用户、需要根据代理开关自动切换的用户;另外直连时插件仍只允许公网地址,可以挡住对本机和内网服务的访问。

环境要求

项目 要求
DeepSeek Harness 桌面版 0.2.1、0.2.2(0.2.2-rc.1 已测)
系统 macOS(已完整验证);Windows、Linux(代码已支持,尚未在真机完整验证)
代理 本机 HTTP 代理或「混合端口」(Clash / mihomo / Clash Verge、Surge、v2rayN 等),不支持 SOCKS、PAC

核心功能

1、自动检测代理。优先读取系统代理设置(macOS 网络设置、Windows Internet 选项、Linux GNOME/KDE 代理设置),找不到再读 DSH 启动时的 HTTPS_PROXY 等环境变量,最后扫描常见端口 7890、7897、6152、1087、10809 等。每个候选地址都会做实际握手验证,确认真的是 HTTP 代理才使用。

2、三种线路:auto(跟随检测结果)、forward(固定走代理)、direct(固定直连)。默认 auto。每次 web_fetch 之前插件会先在本机测一下代理端口,约 1 毫秒,代理刚关也不会走错线路;代理找不到时一律直连,直连的安全检查照常进行。

3、作用范围可切换。默认 web_fetch_only,只有主动选择 global 时其它模块才跟着走这条线路。

4、代理需要账号密码时可手动填写 http://user:pass@地址:端口。密码只保存在本机,权限为 600,界面、日志和提示里一律显示为 ***。

5、web_fetch 的结果里会附上当前状态提示,模型能看到并告诉你。

安装与启用

在 DeepSeek Harness 里对模型说下面这句话,然后完全退出并重新打开 DSH:

用 plugin_manager 安装插件 @lightrivers/dsh-proxy-switch

重启后侧栏底部右边会多出一个小按钮,显示当前线路和状态圆点(例如「走代理 ●」)。

如果以前在 ~/.dsh/.env 里写过 HTTP_PROXY / HTTPS_PROXY,先删掉它们再重启。否则插件关掉后,DSH 还会回到写死的代理。

README 另给出了从源码安装的步骤:下载源码到 ~/dsh-proxy-switch,然后对模型说「用 plugin_manager 安装插件 ~/dsh-proxy-switch」(它会执行 plugin_manager action=install_bundle target=<绝对路径>),再完全退出并重新打开 DSH。升级时在源码目录 git pull,再执行一次安装步骤。本文只转述 README 原文,实际安装请使用上面的官方安装方式。

从 0.4.1 及更早版本升级时(0.4.2 起包名改为 @lightrivers/dsh-proxy-switch),先让模型用 plugin_manager 卸载旧的 dsh-proxy-switch,再按上面的方法安装新版,设置和状态会保留。

典型用法

大多数人装好后什么都不用做。默认是「自动」:插件读取系统代理设置,找到代理端口,代理运行时 web_fetch 走代理,代理关掉后自动改直连。

点侧栏底部的按钮打开面板,主要区域:

  • 最上面一大块:当前走的是哪条线路。线条在流动表示通畅,出问题时符号标在出问题的地方(✕ 表示那里断了,🔒 表示代理要登录,❗ 表示不稳定)。右上角的小标签是作用范围:「仅 web_fetch」或「所有工具」。
  • 自动 / 走代理 / 直连:选线路。
  • 代理那一行:找到的代理地址、怎么找到的(系统代理、环境变量或端口扫描),以及延迟;右边按钮可以重新检测。
  • 更多设置:手动填写代理地址、作用范围、按钮放在哪里。

按钮上的圆点:🟢 正常,🟠 需要处理,🔴 出现问题,⚪ 正在检测。

左侧栏底部可能挤着好几个插件按钮,可以在「更多设置 → 按钮位置」里改成对话顶栏(适合侧栏常收起的人,Windows 上侧栏收起时默认那一行会被隐藏)或不显示。选「不显示」后设置仍在「插件 → 代理开关」页面里。

线路和代理状态对不上时,面板会给一句话说明和一个修复按钮,按按钮上的说明操作即可:固定直连但代理开着时点「改为自动」;代理在运行但找不到端口时点「手动填写地址」,只填端口号(例如 7890)就行。

配置与状态

面板里能改的设置保存在 ~/.dsh/storages/dsh-proxy-switch/state.json(目录权限 0700、文件权限 0600),一般不需要手动编辑。

字段 默认 说明
mode auto auto / forward(固定走代理)/ direct(固定直连)
upstreamSource auto auto 时代理地址由检测结果更新;manual 时只使用手动填写的地址
upstream http://127.0.0.1:1082 代理地址,只接受 http://host:port,可带 user:pass@
scope web_fetch_only web_fetch_only(仅 web_fetch)/ global(所有工具)
listenPort 7899 仅「所有工具」模式使用的本地端口
probeIntervalMs 15000 后台检测代理的间隔(3000–600000 毫秒),界面里不提供修改

按钮位置是浏览器端偏好,保存在 localStorage 的 dsh-proxy-switch.placement 里。

插件另提供本机状态接口:

GET  /dsh-proxy-switch/state
POST /dsh-proxy-switch/mode      { "mode": "auto" | "forward" | "direct" }
POST /dsh-proxy-switch/settings  { "scope"?, "upstream"?, "upstreamSource"?, "listenPort"?, "probeIntervalMs"? }
POST /dsh-proxy-switch/probe     立即检测一次当前代理
POST /dsh-proxy-switch/detect    立即重新查找代理

接口只接受本机请求,Host 必须是 DSH 自己的地址,并校验 Origin、Sec-Fetch-Site;POST 还要求 Content-Type: application/json 和请求头 x-dsh-proxy-switch-request: 1。

工作原理

插件只替换 web_fetch 的「发请求」这一步:请求先进入插件自己的 web_fetch 提供者,再经本机私有通道(随机端口,只监听 127.0.0.1),之后分流到 HTTP 代理或直连目标网站。重定向、超时、大小限制、编码处理仍沿用 DSH 原来的实现。

  • 直连时整组 DNS 结果都必须是公网地址,fake-IP、内网、回环、NAT64 内嵌私网地址等一律拒绝。
  • 走代理时,localhost、.local、.lan 这类本地名字和在本机解析出内网地址的目标会被拒绝,但最终由代理解析,所以只是缓解。
  • 私有通道每次启动生成随机令牌,本机其它程序无法借用它(以及保存的代理账号密码);每个请求使用新连接,切换线路后不会沿用旧的代理隧道。

适用场景与注意

适合:TUN / fake-IP 环境下 DSH web_fetch 失败、只开系统代理没开 TUN、希望代理开关时自动切换线路、希望 web_fetch 结果带状态提示的用户。

需要注意:

  • 只支持 HTTP 代理(或混合端口),不支持 SOCKS、PAC。需要账号密码时用 http://user:pass@host:port 形式手动填写。
  • 目前只在 macOS 上完整验证过,Windows、Linux 代码已支持但尚未真机验证。
  • 插件以当前 DSH 进程的权限运行,安装前建议先读一遍源码和 LICENSE(MIT),确认来源可信。
  • 走代理时的内网访问拦截只能缓解,不能保证百分之百。开着 TUN 时本机只能解析到假地址,插件判断不了真实目标;如果 DNS 被污染把正常网站解析成内网地址,走代理时该网站会被误拒,提示为「转发模式拒绝请求」,打开 TUN 或换可信 DNS 可恢复。
  • README 提醒:插件依赖必须写在 peerDependencies 里,不能写进 dependencies,否则会装出第二份 @deepseek-ai/dsh-http-proxy,「所有工具」模式会静默失效。
  • README 另给出测试命令:npm test(单元测试)、DSH_RUNTIME_MODULES=/path/to/dsh/node_modules node scripts/e2e-host.mjs(真实 Cordis/WebRuntime 集成测试)、node scripts/e2e-real.mjs(可选,经过本机真实 HTTP 代理)、node scripts/e2e-web-fetch-warning.mjs(web_fetch 结果附带的警告文本)。

结尾

dsh-proxy-switch 的价值不在于新增能力,而是把 web_fetch 在代理环境下的线路选择从「手写 HTTP_PROXY 赌一把」变成「自动检测、可一键切换、默认不波及其它工具」。是否安装取决于你平时是否开着 TUN 或只开系统代理。插件目录页:https://www.skillhub.cn/plugins/lightrivers/dsh-proxy-switch ,源码:https://github.com/lightrivers/dsh-proxy-switch 。

羽毛球分组比赛记分
小程序二维码

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

小夜