dsh-remote-access
August 16, 2026 · View on GitHub
DeepSeek Harness WebUI 的远程访问插件:在 DSH 本机 Web 服务前面启动一个带密码验证的反向代理网关,允许从局域网/远程访问 WebUI,同时保持 DSH 自身只监听 127.0.0.1。
工作原理
- DSH 官方出于安全考虑,当前不允许通过
--host 0.0.0.0直接把 WebUI 暴露到网络。 - 本插件不改动 DSH 的监听地址,而是额外启动一个 HTTP/WebSocket 反向代理:
- 默认监听
0.0.0.0:3081; - 所有请求先经过密码验证(登录 Cookie 或 HTTP Basic Auth);
- 验证通过后转发到本机 DSH Web 服务(默认
127.0.0.1:<dsh port>); - 转发时把
Host/Origin重写为本地回环地址,因此 DSH 自带的/api浏览器信任围栏可以正常放行,同时外部无法直接触达未鉴权的 DSH API。
- 默认监听
- WebSocket(会话事件、SSE 升级等)同样经过密码验证后再代理。
安装
# 在 deepseek-harness 仓库根执行
pnpm dsh plugin --profile web add ./dsh-remote-access
# 或从 npm/GitHub 安装后:
# pnpm dsh plugin --profile web add dsh-remote-access
安装后必须设置访问密码,再重启 dsh web。所有配置均从 DSH 配置文件读取,不再使用环境变量。
可以通过 DSH 设置界面的 “远程” 页设置密码,也可以在 profile 的 cordis.patch.yml 或 --patch 覆盖层中配置:
- id: dsh-remote-access
config:
password: 'your-strong-password'
remoteHost: '0.0.0.0'
remotePort: 3081
设置密码
插件不再读取 DSH_REMOTE_ACCESS_PASSWORD 环境变量。密码只通过以下两种方式配置:
- DSH 设置界面 “远程” 页;
- profile 的
cordis.patch.yml或--patch覆盖层。
例如在 profile 配置文件中设置:
- id: dsh-remote-access
config:
enabled: true
remoteHost: '0.0.0.0'
remotePort: 3081
password: 'your-strong-password'
sessionTtlMs: 604800000
maxSessions: 100
注意 config 是整块替换,需要重述全部键。通过设置界面保存的密码会加密后写入 DSH 的 settings.yaml。
开发期加载
# 从 deepseek-harness 仓库根执行
pnpm dsh web --patch /abs/path/to/dsh-remote-access/cordis.yml
打开 http://<本机局域网IP>:3081,先看到登录页;输入密码后进入 DSH WebUI。
配置项
| 配置 | 默认值 | 说明 |
|---|---|---|
enabled | true | 是否启动远程网关 |
remoteHost | 0.0.0.0 | 远程网关监听地址;0.0.0.0 表示所有网卡 |
remotePort | 3081 | 远程网关监听端口 |
targetHost | 127.0.0.1 | 转发目标 DSH 地址 |
targetPort | 自动 | 转发目标 DSH 端口;缺省使用当前 webServer 服务端口 |
password | 空 | 访问密码;为空且启用时远程网关不启动 |
enableCaptcha | false | 是否启用登录验证码 |
maxAttemptsPerDay | 20 | 每个 IP 在 24 小时内最大失败登录次数 |
maxAttemptsPer5h | 10 | 每个 IP 在 5 小时内最大失败登录次数 |
sessionTtlMs | 604800000 | 登录 Cookie 有效期(毫秒,默认 7 天) |
maxSessions | 100 | 内存中最大并发会话数 |
title | DeepSeek Harness Remote Access | 登录页标题 |
设置界面
插件会在 DSH 设置界面新增一个 “远程” 页,可以修改:
- 是否启用远程访问
- 远程端口
- 访问密码
- 是否启用验证码
- 每日登录尝试限额(24 小时)
- 5 小时内登录尝试限额
该页面通过插件自己的 /plugins/dsh-remote-access/settings 路由读写配置,因此不依赖 DSH 的 apiproxy 设置白名单,适合作为外部插件分发。
用独立 profile 测试
不要直接改正在使用的 web profile;新开一个测试 profile:
# 1. 创建 profile 并加入本插件
dsh plugin --profile remote-access-test add /abs/path/to/dsh-remote-access
# 2. 如果该 profile 需要 WebUI,把 @deepseek-ai/dsh-web-app 加入
# $DSH_HOME/profiles/remote-access-test/package.json 的 dsh.profile.bundles
# 3. 启动(端口按需修改;密码在配置文件中或设置界面中配置)
dsh --profile remote-access-test --port 8221
启动后:
- DSH WebUI 本机地址:
http://127.0.0.1:8221 - 远程访问网关:
http://<本机IP>:3081(先登录,再进入 WebUI)
验证
# 未认证请求应返回 401
curl -i http://127.0.0.1:3081/
# Basic Auth 可访问 DSH 页面/API
curl -u admin:'your-strong-password' http://127.0.0.1:3081/api/session.list
浏览器访问时,未登录会看到登录页;登录后 Cookie 会自动用于后续 HTTP 与 WebSocket 请求。
安全说明
- 不要使用弱密码。远程暴露的是完整 DSH WebUI,包含 Shell/文件系统等 agent 能力,等同于远程代码执行面。
- 密码不会明文写入
settings.yaml,保存时会使用 AES-256-GCM 加密;加密密钥保存在$DSH_HOME/.dsh-remote-access.key。如果密钥丢失或密文损坏导致无法解密,插件会阻止所有登录,并在远程网关登录页显示警告。 - 默认走 HTTP,密码和会话 Cookie 在网络上是明文传输。生产环境请在前面加 TLS 反向代理(如 Caddy/nginx),或自行扩展 HTTPS。
- 会话只保存在进程内存中,DSH 重启后所有登录会话失效,需要重新登录。
- 登录失败会按 IP 记录;超过每日或 5 小时限额后返回
429 Too Many Requests。验证码为一次性算术题,启用后每次登录都需要重新填写。 - 本插件是“网关鉴权”,不替代 DSH 自身的权限模式。登录后获得的仍是 DSH 当前用户的权限。
文件结构
src/index.ts— Host 插件实现(反向代理 + 密码验证 + 设置路由)src/client/— 浏览器半(设置页“远程”)tsdown.config.ts— Client bundle 构建配置cordis.patch.yml— bundle 安装补丁cordis.yml— 开发期--patch挂载package.json/tsconfig.json— 构建配置