dsh-plugin-proxy-env
DSH plugin: inject proxy environment variables at startup and self-check the whole proxy chain
- Stars
- 0
- Language
- JavaScript
- Created
- Sep 10, 2026
- Updated
- Sep 10, 2026
Introduction
dsh-plugin-proxy-env
DSH 插件:启动时自动注入代理环境变量,并自检整条代理链路。 A DeepSeek Harness plugin that injects proxy environment variables at startup and self-checks the whole proxy chain.
中文
这是什么
一个 DSH 插件,做两件事:
- 启动时注入代理变量——把
HTTP_PROXY/HTTPS_PROXY/NODE_USE_ENV_PROXY/NO_PROXY写进 harness 主进程的环境,之后所有子进程(shell、git、npm、python)自动继承,不用再setx+ 重启。 - 自检——从本地端口一路查到端到端请求,把结论写进日志和报告文件;同时注册一个
proxy_env_check工具,随时能再查一次。
为什么这样能生效
DSH 在派生子进程时从 process.env 构造子环境(dsh-subprocess 的 scrubbedParentEnv(),它只剔除名字含 KEY/PASSWORD/SECRET/TOKEN 的和 DSH_* 的变量,代理变量是刻意保留的)。所以插件在加载阶段写一次 process.env,后面每一次 spawn 都带着它——比手工 setx 更即时,也不依赖启动方式。
注入哪些变量
| 变量 | 值 | 作用 |
|---|---|---|
HTTP_PROXY / HTTPS_PROXY | 解析到的代理地址 | curl / git / python / Go 等自动读取 |
NODE_USE_ENV_PROXY | 1 | 子 Node 进程启动时即让内置 fetch 读取上面的变量 |
NO_PROXY | 默认 localhost,127.0.0.1,::1,api.deepseek.com | 回环必须排除,否则本地 GUI 请求会被塞进代理;模型 API 排除后,代理挂掉也不影响对话 |
已存在的同名变量默认不覆盖(
override: true可强制)。
自检做什么
按「由近到远」的顺序,先报最上游的断点:
- 代理端口是否监听
- 端口是否应答
CONNECT(手工建隧道,不依赖 undici) - DNS 是否返回真实地址(识别
198.18.0.0/15与fdfe:dcba:9876::/64的 fake-ip) - 直连探针 + 走代理探针(TLS 隧道)
- 汇总结论:
PASS/WARN/FAIL+ 一条修复建议
结果写入 $DSH_HOME/proxy-env/report.json,agent 可以直接读取,不必调用工具。
安装
方式一:DSH Desktop 插件管理器(推荐)
设置 → 插件 → 安装,填入 dsh-plugin-proxy-env(发布到 npm 后可用)。
方式二:手动(从本仓库安装)
# 1) 进入当前 profile 目录
cd "$env:DSH_HOME\profiles\desktop"
# 2) 安装(本地路径、git 或 npm 均可)
pnpm add file:D:/path/to/dsh-plugin-proxy-env
# 或 pnpm add github:looeton/dsh-plugin-proxy-env
# 3) 把包名加进 package.json 的 dsh.profile.bundles
# "dsh": { "profile": { "bundles": [ ..., "dsh-plugin-proxy-env" ] } }
# 4) 重启 DSH Desktop
方式三:先本地验证,不装进 profile
node src/cli.mjs # 独立自检,跟插件走同一套代码
node --test tests/*.test.mjs # 52 个单元测试
配置项
通过 patch 行或 profile 的 cordis.patch.yml 传入:
- id: proxy-env
config:
proxyUrl: http://127.0.0.1:7897 # 留空则自动探测
noProxy: localhost,127.0.0.1,::1,api.deepseek.com
selfCheck: true
tool: true
| 键 | 默认 | 说明 |
|---|---|---|
enable | true | 总开关 |
proxyUrl | 自动 | 完整代理地址;留空则按 port → Windows 系统代理 → 已导出的环境变量顺序解析 |
host | 127.0.0.1 | 本地代理主机 |
port | 0 | 直接指定端口 |
noProxy | 见上 | NO_PROXY 内容 |
override | false | 是否覆盖已存在的同名变量 |
patchGlobalDispatcher | true | 动态 import undici,把全局 dispatcher 换成 EnvHttpProxyAgent,让运行时的 Node 请求也走代理 |
selfCheck | true | 启动时自检 |
writeReport | true | 写 $DSH_HOME/proxy-env/report.json |
tool | true | 注册 proxy_env_check 工具 |
probeUrl | https://www.google.com | 只有走代理才通的探针 |
directProbeUrl | https://example.com | 直连探针 |
dnsHost | example.com | fake-ip 检测域名 |
timeoutMs | 15000 | 单个探针超时 |
提供的工具
| 工具 | 参数 | 返回 |
|---|---|---|
proxy_env_check | probe_url、skip_network | 一行结论 + 完整链路文本 |
局限
- 它管的是进程环境,不是
web_fetch。DSH 的web_fetch用固定 IP 的自定义 undiciAgent(防 SSRF / DNS rebinding),刻意绕过全局 dispatcher,所以即使代理正常它也不会走代理——这是设计,不是本插件的缺陷。被墙站点请用能走云端的抓取工具,或让 agent 用 shell 里的node/python抓。 - 注册表读取依赖
reg.exe,且用文件重定向而非管道(受限令牌沙箱里管道会 EPERM)。读不到时自动回退到已导出的HTTPS_PROXY/HTTP_PROXY。 - 非 Windows 只走配置和环境变量,不读系统代理。
patchGlobalDispatcher是运行时切换:它需要能解析到undici,且版本要有EnvHttpProxyAgent(唯一会遵守NO_PROXY的实现);不满足时跳过并在日志里说明。
相关项目
- clash-verge-system-proxy —— 手工版完整指南(关 TUN、开系统代理、写变量、排错手册)
- proxy-doctor —— 独立的 PowerShell 诊断工具,不装插件也能用
English
What this is
A DSH plugin that does two things:
- Injects proxy variables at startup — writes
HTTP_PROXY/HTTPS_PROXY/NODE_USE_ENV_PROXY/NO_PROXYinto the harness host process, so every child process (shell, git, npm, python) inherits them. Nosetx, no restart dance. - Self-checks the chain — walks from the local port to a real request, logs a verdict, writes a report file, and registers a
proxy_env_checktool for on-demand re-runs.
Why this works
DSH builds each child environment from process.env at spawn time (scrubbedParentEnv() in dsh-subprocess strips credential-shaped names and DSH_*, but keeps proxy variables on purpose). Writing process.env once during plugin load therefore covers every later spawn — immediately, and independent of how the app was launched.
What it injects
| Variable | Value | Purpose |
|---|---|---|
HTTP_PROXY / HTTPS_PROXY | resolved proxy URL | read by curl, git, python, Go, … |
NODE_USE_ENV_PROXY | 1 | makes child Node processes honour the two above from bootstrap |
NO_PROXY | localhost,127.0.0.1,::1,api.deepseek.com | loopback must be excluded or local GUI requests go through the proxy; the model API is excluded so a dead proxy cannot break chat |
Existing values are left alone unless
override: true.
What the self-check does
Nearest-first, so the report always names the earliest broken link:
- is the proxy port listening
- does it answer
CONNECT(hand-built tunnel, no undici needed) - does DNS return real addresses (detects
198.18.0.0/15andfdfe:dcba:9876::/64fake-ip) - direct probe + through-proxy probe (TLS tunnel)
- one verdict —
PASS/WARN/FAIL— plus one fix
The report lands in $DSH_HOME/proxy-env/report.json, readable by the agent without a tool call.
Install
Option 1 — DSH Desktop plugin manager (recommended): Settings → Plugins → Install, then dsh-plugin-proxy-env (available once published to npm).
Option 2 — manual, from this repository
cd "$env:DSH_HOME\profiles\desktop"
pnpm add file:D:/path/to/dsh-plugin-proxy-env # or github:looeton/dsh-plugin-proxy-env
# add "dsh-plugin-proxy-env" to dsh.profile.bundles in package.json
# restart DSH Desktop
Option 3 — verify locally without installing
node src/cli.mjs # standalone self-check, same code path
node --test tests/*.test.mjs # 52 unit tests
Configuration
- id: proxy-env
config:
proxyUrl: http://127.0.0.1:7897 # empty = auto-detect
noProxy: localhost,127.0.0.1,::1,api.deepseek.com
selfCheck: true
tool: true
| Key | Default | Purpose |
|---|---|---|
enable | true | master switch |
proxyUrl | auto | full proxy URL; when empty the order is port → Windows system proxy → exported env var |
host | 127.0.0.1 | local proxy host |
port | 0 | explicit port |
noProxy | see above | NO_PROXY contents |
override | false | overwrite existing variables |
patchGlobalDispatcher | true | dynamically import undici and switch the global dispatcher to EnvHttpProxyAgent, so runtime Node requests use the proxy too |
selfCheck | true | run the check at startup |
writeReport | true | write $DSH_HOME/proxy-env/report.json |
tool | true | register the proxy_env_check tool |
probeUrl | https://www.google.com | only reachable through the proxy |
directProbeUrl | https://example.com | reachable directly |
dnsHost | example.com | host used for the fake-ip check |
timeoutMs | 15000 | per-probe timeout |
The tool it registers
| Tool | Arguments | Returns |
|---|---|---|
proxy_env_check | probe_url, skip_network | one-line verdict plus the full chain report |
Limitations
- It covers process environment, not
web_fetch. DSH'sweb_fetchpins connections with a custom undiciAgent(SSRF / DNS-rebinding defence) and bypasses the global dispatcher by design, so it will not use the proxy even when everything else does. For blocked sites use a cloud-based page reader, or have the agent fetch withnode/pythonfrom a shell. - Registry reading shells out to
reg.exe, with stdout redirected to a temp file rather than a pipe (pipes fail with EPERM inside restricted-token sandboxes). When unreadable it falls back to an exportedHTTPS_PROXY/HTTP_PROXY. - Non-Windows hosts use configuration and environment variables only.
patchGlobalDispatcheris a runtime switch: it needsundicito resolve and a version that shipsEnvHttpProxyAgent(the only variant that honoursNO_PROXY). Otherwise it is skipped and logged.
Related projects
- clash-verge-system-proxy — the manual companion guide (TUN off, system proxy on, variables, troubleshooting)
- proxy-doctor — standalone PowerShell diagnosis, no plugin needed
Development
node --check src/*.mjs # or: npm run check
npm test # or: node --test tests/*.test.mjs
node src/cli.mjs # self-check against the current machine