dsh-system-proxy:DSH 出站 HTTP(S) 路由插件

前言

DSH 的理念是插件化,插件和模型调用经常要访问外部 HTTP/HTTPS 接口。实际运行中,目标地址、provider、plugin 可能不同;有的请求需要直连,有的请求需要走代理;直连失败时还需要安全地换到代理。

dsh-system-proxy 把这类出站路由放到 DSH host plugin 层处理,避免每个插件各自拼接代理逻辑。

这是什么

dsh-system-proxy 是一个 DSH host plugin,用于在 DSH 主进程中统一处理出站 HTTP/HTTPS 路由。仓库地址所有者为 khiqwq,源码仓库是 https://github.com/khiqwq/dsh-system-proxy

它解决的核心问题是:

  • HTTP、HTTPS、SOCKS4、SOCKS4a、SOCKS5、SOCKS5h 代理;
  • 多个具名代理(named proxies);
  • hostproviderplugin 路由;
  • directproxyfallbackblock 四种动作;
  • 直连失败或延迟过高时使用代理保底;
  • 每目标 EWMA 延迟、失败冷却(cooldown)与健康记忆;
  • 显式 provider / plugin 上下文,不伪造调用方身份;
  • 代理凭据脱敏、安全日志和热重载恢复;
  • 包装 globalThis.fetch
  • patchNodeHttp: true 时包装 node:http / node:httpsrequestget
  • 内网 / 云元数据端点的默认保护;
  • 交互式配置卡;
  • passwordRef / credentials 保存密码。

运行要求 Node >=22。

核心能力

路由动作

插件把出站请求归到四类动作:

  1. direct:只直连。
  2. proxy:强制使用指定具名代理。
  3. fallback:先直连,满足条件时改用代理。
  4. block:本地拒绝请求。

引用不存在或当前不可用的代理名会报 UNKNOWN_PROXY,不会静默降级直连。

fetch 与 node http/https

插件会包装 globalThis.fetch。配置中启用 patchNodeHttp: true 时,还会包装 node:http / node:httpsrequestget

这是进程级全局补丁。同一进程内不应同时加载多个相互竞争的传输包装插件。

provider / plugin 上下文

全局 fetch 本身不能可靠判断请求来自哪个插件。调用方需要显式提供上下文:

await ctx.networkRoute.run({ provider: 'openai', plugin: 'my-plugin' }, () => fetch('https://api.openai.com/v1/models'))

对于流式响应,可以用 iterable 包装惰性异步迭代器:

const attributed = ctx.networkRoute.iterable({ provider: 'openai' }, response.body)

这样在消费 response.body 时,可以保留 provider / plugin 归属。

安全与回退

自动回退不是普通重试。默认只允许 GETHEADOPTIONSTRACE 自动换路;POST 默认不重放。

以下情况不重放:

  • 流式上传;
  • FormData
  • 超出缓冲上限的 body
  • 用户主动 abort
  • 已经收到响应头或 SSE 字节;
  • 无法证明请求字节尚未写出的连接后失败。

只有连接前失败才安全换路。主动健康探测默认关闭。

内网与云元数据保护

安全默认让 localhostloopback169.254.0.0/16、云 metadata 端点、RFC1918 内网和 IPv6 ULA 一律直连。内网和云 metadata 流量因此保持直连,不会被交给外部代理。

密码与凭据

插件支持 passwordRef / credentials 保存代理密码。密码仅通过单向 credentials.set() 提交,绝不会保存到 settings;保存后密码草稿立即清空。

trustRouteHeaders 默认关闭;内部路由控制头会在发出请求前自动剥离。

SOCKS 限制

SOCKS4 / SOCKS4a 面对 IPv6 目标时,会在握手前显式抛错 SOCKS4_IPV6_UNSUPPORTED,不会静默直连。

安装与启用

发布后可在对应 profile 中安装:

dsh plugin --profile <name> add dsh-system-proxy

运行环境需要 Node >=22。

安装前应检查源码与许可证,并确认插件以当前 dsh 进程权限运行是否符合预期。

配置与覆盖

配置位于 profile 的 cordis.patch.yml。基本结构是:

  • proxies 是对象,用来声明多个具名代理;
  • rules 是数组,用来描述路由规则;
  • default 是对象,用来声明默认策略。

Loader 配置是整体替换:增加一条规则时,必须重述完整 config,不能只写增量字段。

环境变量可用于覆盖或禁用:

DSH_PROXY_URL
DSH_PROXY_MODE
DSH_PROXY_DISABLE
NO_PROXY/no_proxy

适用场景

适合以下情况:

  • 在 DSH 中统一处理出站 HTTP/HTTPS 请求;
  • 按目标主机、provider、plugin 选择直连或代理;
  • 直连优先,并在连接前失败时回退到代理;
  • 保护 localhostloopback、云 metadata 和 RFC1918 内网地址不被外部代理转发;
  • 需要为代理密码使用 passwordRef / credentials,而不是把密码写入 settings。

链接

源码仓库:https://github.com/khiqwq/dsh-system-proxy

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

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

小夜