deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
INSTALL REFERENCE
dsh plugin --profile web add github:ffdnm/ClashTUNWithDSH
该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。
PROJECT README
English | 中文
A DSH (DeepSeek Harness) plugin that removes the resolves to a non-public IP address restriction so DSH works with Clash TUN.
This project is released under GNU AGPL-3.0-or-later: you are free to use, modify, and redistribute it; any redistribution (including offering it as a network service) must open-source the code under the same license. See the LICENSE file at the repository root.
The built-in web_fetch tool in DSH carries an SSRF guard: before fetching, it resolves the hostname to IP addresses, and if any resolved address is a non-public IP (loopback, private, reserved ranges, etc.), it rejects the request outright:
URL hostname "example.com" resolves to a non-public IP address (WEB_BLOCKED_URL)
Under Clash TUN (fake-ip mode), however, system DNS is taken over by Clash: every domain resolves to a fake-ip reserved-range address such as 198.18.0.0/15 (or fdfe:dcba:9876::/48), and the real connection is intercepted by the TUN virtual adapter and handed to Clash for proxying per its rules. This is completely transparent to ordinary apps, yet it lands exactly on DSH's "non-public IP" tripwire — with Clash TUN enabled, nearly every web_fetch request is rejected.
This plugin removes that restriction: any resolved IP is allowed. The connection is still initiated directly and the TUN adapter takes it over unchanged, so DSH works normally under Clash TUN.
DSH's fetch pipeline is: the web_fetch tool → ctx.web (the WebRuntime service) → the local HTTP fetch provider (web-fetch-http, id http). The IP check only happens inside the provider instance's resolveAddresses method (after DNS resolution, it verifies every answer is public unicast).
This plugin (a Cordis dynamic plugin, host side) swaps that method in place at runtime:
WEB_BLOCKED_URL with a message containing non-public, the plugin spawns a one-shot Node child process through DSH's subprocess service and re-resolves via dns.lookup(..., { all: true, order: 'verbatim' }) through the system resolver (which, under Clash TUN, returns the fake-ip), allows every returned address, and hands the address set to the stock address-pinned transport — the TUN adapter intercepts the connection and Clash proxies it as usual.127.0.0.1, [::1]) are allowed as well; resolved answers are cached for 60 seconds per process to avoid spawning a child process repeatedly.No DSH source modification, no deployment config change, no second provider registration (so provider selection is untouched); the patch follows the plugin lifecycle exactly.
The repository ships install.ps1 (Windows PowerShell) and install.sh (macOS/Linux/Git Bash). One command installs everything:
# Windows (PowerShell 5.1+)
.\install.ps1 # install
.\install.ps1 -Uninstall # uninstall
# macOS / Linux / Git Bash
./install.sh # install
./install.sh uninstall # uninstall
What gets installed (into $DSH_HOME, i.e. $env:DSH_HOME or ~/.dsh):
| File | Purpose |
|---|---|
clash-tun-web-fetch-unlock.cjs |
Host-plane plugin module (a copy of the file in payload/) |
cordis.patch.yml |
DSH's official home-directory user patch layer; the script idempotently appends a marked block (# >>> classtunwithdsh) with one insert row that mounts the plugin into the host composition |
Highlights:
Besides the one-click install, you can alternatively define a dynamic plugin in a session: use the function body of clash-tun-web-fetch-unlock.host.js as cordis_define's code.host (idPrefix: "clash"), then activate it with cordis_run — same effect, but it only lives in the current DSH process and must be re-loaded after a restart. Either way works; enabling both at once is safe (the patch carries ref-counting and restore protection).
Run each request once before and once after installing (the DSH Web GUI listens on 127.0.0.1:3080 by default):
| Request | Before | After |
|---|---|---|
web_fetch http://127.0.0.1:3080/ |
URL hostname "127.0.0.1" resolves to a non-public IP address |
HTTP 401 (the GUI auth response — the connection actually happened) |
web_fetch http://localhost:3080/ |
blocked the same way | HTTP 401 |
web_fetch https://example.com/ |
HTTP 200 | HTTP 200 (public path, no regression) |
web_fetch can reach local and intranet addresses. Use it only on personal devices and trusted networks such as Clash TUN, and never let untrusted model instructions steer fetches toward sensitive internal services.[clash-tun-web] allowed non-public destination: <host> -> <ip,...> for observability.| File | Purpose |
|---|---|
README.md |
This document (English) |
README_CN.md |
Chinese documentation |
LICENSE |
GNU AGPL-3.0 license text |
install.ps1 / install.sh |
One-click install / uninstall (Windows PowerShell / POSIX shell) |
payload/clash-tun-web-fetch-unlock.cjs |
Install payload: the host-plane plugin module (CJS, module.exports = { apply }) |
clash-tun-web-fetch-unlock.host.js |
In-session dynamic plugin source (cordis_define's code.host body; same logic as the payload) |
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。