前言¶
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);
- 按
host、provider、plugin路由; direct、proxy、fallback、block四種動作;- 直連失敗或延遲過高時使用代理保底;
- 每目標 EWMA 延遲、失敗冷卻(cooldown)與健康記憶;
- 顯式
provider/plugin上下文,不僞造調用方身份; - 代理憑據脫敏、安全日誌和熱重載恢復;
- 包裝
globalThis.fetch; patchNodeHttp: true時包裝node:http/node:https的request與get;- 內網 / 雲元數據端點的默認保護;
- 交互式配置卡;
passwordRef/credentials保存密碼。
運行要求 Node >=22。
核心能力¶
路由動作¶
插件把出站請求歸到四類動作:
direct:只直連。proxy:強制使用指定具名代理。fallback:先直連,滿足條件時改用代理。block:本地拒絕請求。
引用不存在或當前不可用的代理名會報 UNKNOWN_PROXY,不會靜默降級直連。
fetch 與 node http/https¶
插件會包裝 globalThis.fetch。配置中啓用 patchNodeHttp: true 時,還會包裝 node:http / node:https 的 request 與 get。
這是進程級全局補丁。同一進程內不應同時加載多個相互競爭的傳輸包裝插件。
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 歸屬。
安全與回退¶
自動回退不是普通重試。默認只允許 GET、HEAD、OPTIONS、TRACE 自動換路;POST 默認不重放。
以下情況不重放:
- 流式上傳;
FormData;- 超出緩衝上限的
body; - 用戶主動
abort; - 已經收到響應頭或 SSE 字節;
- 無法證明請求字節尚未寫出的連接後失敗。
只有連接前失敗才安全換路。主動健康探測默認關閉。
內網與雲元數據保護¶
安全默認讓 localhost、loopback、169.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 選擇直連或代理;
- 直連優先,並在連接前失敗時回退到代理;
- 保護
localhost、loopback、雲 metadata 和 RFC1918 內網地址不被外部代理轉發; - 需要爲代理密碼使用
passwordRef/credentials,而不是把密碼寫入 settings。