DeepSeek Harness 插件

slywalker2006/dsh-passwords

Star 数 ★ 1 分类 开发与运行时 收录于 2026-08-14

DSH Web UI 登录网关:首次配置、bcrypt + 静态加密(AES-256-GCM/HMAC)、防爆破、审计日志、TLS 1.2+ 与 80→443 跳转、CSRF 与防嵌框。

安装

# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)

dsh plugin --profile web add github:slywalker2006/dsh-passwords

GitHub 来源的插件在安装时会在你的机器上执行构建脚本。请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。

README

给 DeepSeek Harness(dsh)的网页界面加一道密码门

dsh 自带的网页界面没有任何登录功能——只要别人知道你的服务器地址,打开就能用,还能烧你的 API key。这个项目在 dsh 前面挡一层登录页:没登录的人一律先看到登录页,输对账号密码才放进去。

🏅 已收录于 Awesome DeepSeek Harness 生态索引(Infrastructure & Development)与 Awesome DSH Plugin 插件精选列表(Development & Runtime)。

名字的由来:这个项目最早叫 dsh-mcp-platform(当时带 MCP 功能),后来 MCP 删了,只剩一个登录网关,就改名 dsh-passwords——好记:dsh 的密码门。

它做了什么

  • 登录页 + 首次配置页(第一次访问先设管理员账号)
  • 登录一次管 12 小时(Cookie 会话,关浏览器也不丢)
  • 密码用 bcrypt 哈希存库,乱试密码 5 次锁 15 分钟
  • 每一步都有审计日志,一条命令就能看谁在什么时候登录/失败过
  • 用户数据全部加密落盘:用户名、IP、审计记录都是密文,就算数据库文件被偷走也看不懂
  • 支持 HTTPS + 80 端口自动跳转(强烈建议公网开启)
  • 登录页自动跟着 dsh 的主题走(dsh 用深色它就深色)

界面截图

登录页(浅色 · 跟随系统) 登录页(深色 · 跟随 dsh 主题)
首次配置页(首次访问) dsh 主界面(登录后)
安全测试实测输出 核心源码(auth.ts)

本地先跑起来看看

需要 Node.js 22.5 以上node -v 看一眼)。

npm install           # 装依赖
cp .env.example .env  # 复制出配置文件
npm run build         # 编译
npm start             # 启动,浏览器打开 http://localhost:8080

启动前记得改 .env 里的 SETUP_KEY(下面讲它是什么)。

SETUP_KEY 是什么?在哪?

SETUP_KEY安装密钥。第一次打开网页时会进入"首次配置"页,要求输入它,输对了才能创建管理员账号。作用就是防止陌生人抢在你前面把平台初始化了。

它在项目根目录的 .env 文件里,就是这一行:

SETUP_KEY=change-me-to-a-strong-random-key

操作很简单:

  1. 打开 .env,找到 SETUP_KEY= 这一行
  2. 把等号后面换成你自己生成的随机串:
    openssl rand -hex 24   # Linux/macOS 上跑,输出一串随机字符
    
  3. 保存,重启网关
  4. 打开网页,在"预设密钥"框里输入刚才这串值

⚠ 不改成随机值的话网关会拒绝启动。初始化完成后这个密钥就没用了,之后登录只认账号密码。

部署到服务器(跟着抄就行)

1. 装 Node.js 22+

curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get install -y nodejs
node -v   # 确认 >= v22.5.0

2. 装 dsh 并准备 API key

npm install -g @deepseek-ai/dsh

去 DeepSeek 开放平台拿一个 API key(sk- 开头),等会要用。

3. 下载本项目

cd /opt
git clone https://github.com/slywalker2006/dsh-passwords.git
cd dsh-passwords
npm install
cp .env.example .env

打开 .env 改三处:

改哪里 改成什么
SETUP_KEY=... 必须改,openssl rand -hex 24 生成
MCP_GATEWAY_PORT=8080 想对公网开放的端口,比如 80
MCP_DB_ENC_KEY= 填上 openssl rand -hex 32 生成的值(数据加密密钥,设了就不能改
npm run build

4. 用 systemd 托管两个进程(重启服务器自动拉起)

dsh 服务(/etc/systemd/system/dsh-web.service):

[Unit]
Description=DeepSeek Harness web
After=network.target

[Service]
Type=simple
Environment=DEEPSEEK_API_KEY=sk-你的key
ExecStart=/usr/local/bin/dsh web --patch /opt/dsh-passwords/cordis.yml
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

网关服务(/etc/systemd/system/dsh-gateway.service):

[Unit]
Description=dsh-passwords login gateway
After=network.target

[Service]
Type=simple
WorkingDirectory=/opt/dsh-passwords
ExecStart=/usr/local/bin/node dist/index.js serve-gateway
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now dsh-web dsh-gateway
sudo systemctl status dsh-web dsh-gateway   # 两个都 active 就对了

5. 防火墙放行

sudo ufw allow 80/tcp

⚠ 云服务器(阿里云/腾讯云等)还要去控制台的安全组里放行同一个端口,只配 ufw 是没用的。

6. 浏览器完成首次配置

访问 http://你的服务器IP → 输 .env 里的 SETUP_KEY → 创建管理员账号。之后所有人访问都先过登录页。

7. 强烈建议:开 HTTPS

明文 HTTP 下密码会被中间人抓包。开 HTTPS 三步:

cd /opt/dsh-passwords

# 1) 自签证书(用 EC 椭圆曲线,别用 RSA!RSA 握手在弱 CPU 服务器上可能要 1 秒以上,
#    EC 只要几毫秒;IP 换成你的服务器 IP;有域名建议用 Let's Encrypt)
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -keyout tls.key -out tls.crt \
  -days 825 -nodes -subj "/CN=你的IP" -addext "subjectAltName=IP:你的IP"
chmod 600 tls.key

# 2) .env 里改成这样:
#   MCP_GATEWAY_PORT=443
#   MCP_GATEWAY_TLS_CERT=/opt/dsh-passwords/tls.crt
#   MCP_GATEWAY_TLS_KEY=/opt/dsh-passwords/tls.key
#   MCP_GATEWAY_REDIRECT_PORT=80

# 3) 重启 + 放行 443
sudo systemctl restart dsh-gateway
sudo ufw allow 443/tcp   # 安全组同样要放行 443

之后 http:// 会自动跳到 https://。自签证书浏览器第一次会提示不安全,点"继续前往"就行。

dsh 怎么启动(重要)

dsh 和网关是两个独立进程,都要跑起来才能用。启动 dsh 的命令:

DEEPSEEK_API_KEY=sk-你的key dsh web --patch /opt/dsh-passwords/cordis.yml

两个参数说明:

  • DEEPSEEK_API_KEY=...必填。dsh 调模型用的 API key。
  • --patch .../cordis.yml远程访问时强烈建议加。不加的话,网页上点"添加工作区"会尝试弹出你电脑本地的系统文件夹选择器——但你是远程访问服务器的,浏览器根本弹不出本机选择器,表现就是点添加工作区没反应/报错(pickDirectory 失败)。加上这个参数后,点"添加工作区"会在网页内弹出服务器目录浏览器,直接浏览并选择服务器上的文件夹(也能手动输入绝对路径,比如 /opt/myapp)。

不想每次敲参数:把 cordis.yml 的内容合并进 ~/.dsh/profiles/web/cordis.patch.yml,之后直接 dsh web 就永久生效。

上面第 4 步的 systemd 配置里已经带上了 --patch,跟着教程走就不用管这节。

配置速查表

变量 默认值 干什么的
SETUP_KEY 必填 首次配置的安装密钥(在 .env 里)
MCP_DB_PATH ./data/platform.db 数据库文件放哪(自动建库,不需要装 MySQL)
MCP_DB_ENC_KEY 数据加密密钥。openssl rand -hex 32 生成。设了就不能换,换钥匙旧数据全废
MCP_GATEWAY_HOST 0.0.0.0 网关监听地址
MCP_GATEWAY_PORT 8080 网关端口
MCP_GATEWAY_UPSTREAM http://127.0.0.1:3080 dsh 网页的地址(保持默认)
MCP_GATEWAY_TLS_CERT / MCP_GATEWAY_TLS_KEY 两个都填就开 HTTPS
MCP_GATEWAY_REDIRECT_PORT 80 后 80 端口只做跳转
MCP_GATEWAY_PUBLIC_HOST 跳转固定用的公网 IP/域名(防 Host 伪造反射)
MCP_DSH_SETTINGS_FILE 自动找 ~/.dsh/settings.yaml 网关和 dsh 不在同一台机器时才要填

常用命令

npm start                              # 启动网关
node dist/index.js audit --limit 20    # 看最近 20 条审计日志(自动解密)
node dist/index.js serve-gateway --port 9000   # 换个端口启动

常见问题

  • 登录页一直显示"首次配置"? 说明用户表是空的(新库或数据库被删过)。停服 → 删 data/platform.db → 重启 → 重新配置。
  • 忘记管理员密码? 停服后跑 node -e "const {DatabaseSync}=require('node:sqlite');const db=new DatabaseSync('data/platform.db');db.exec('DELETE FROM users;')",重启后重新配置。
  • dsh 报 crypto.randomUUID is not a function 旧版网关没有 HTML 注入兼容层,更新代码后强刷浏览器(Ctrl+Shift+R)。
  • 数据库文件被偷了要紧吗? 不要紧。敏感字段全是 AES-256-GCM 密文或 HMAC 散列,没有 MCP_DB_ENC_KEY 解不开;密码本身只有 bcrypt 哈希,本来就没有明文。
  • 想换 MCP_DB_ENC_KEY 不行。这个密钥一旦启用就不能换,换了一切历史数据都解不开。备份数据库时必须连 .env 一起备份。
  • 访问有点慢? 网关本身每次请求只花约 1-2ms。先查 TLS 握手:curl -sk -o /dev/null -w "TCP:%{time_connect}s TLS:%{time_appconnect}s\n" https://你的IP/gateway/login——如果 TLS 那项要几百毫秒以上,多半是用了 RSA 证书(弱 CPU 服务器上 RSA 握手签名非常慢),换成 EC 证书即可(见第 7 步命令)。TCP 快、TLS 也快但还是慢的话,就是你的网络/代理到服务器的链路延迟,代码解决不了。
  • 每次进去都卡在 "Loading plugins…"? 这是 dsh 在加载它的 ~30 个插件脚本,而 dsh 对插件/静态资源返回的是 no-cache,浏览器每次都要全部重新下载。v2.0.4 起网关对 /assets/* 和带 rev=/plugins/* 强制一年期 immutable 缓存(文件名/rev 都是内容哈希,dsh 更新会自动换新地址)。升级后第一次访问仍会完整下载一次,之后刷新秒进;如果升级后还慢,强刷一次浏览器(Ctrl+Shift+R)让新响应头生效。
  • npm 装 dsh 报错(allow-scripts / node-pty)?npm config set allow-scripts=... --location=user 并装 sudo apt install build-essential(本项目自己没这个问题,是 dsh 的依赖要编译)。

安全清单(都做了)

  • 密码 bcrypt 哈希;安装密钥一次性使用;会话 12 小时 HttpOnly Cookie
  • 暴力破解:5 次失败锁 15 分钟;SQL 注入三层防护
  • HTTPS:TLS 1.2 起步、Cookie Secure、HSTS、80 只跳转
  • 登录页安全头:严格 CSP、防点击劫持、禁缓存、禁嗅探
  • 数据静态加密:用户名/IP/审计记录密文落盘,旧明文自动迁移并清残留
  • 源码里没有任何秘密(密钥全在 .env 和数据库里),源码公开不影响安全
  • 路径穿越防护:/gateway/../api/xxx 类请求先规范化再鉴权,未登录一律拦下
  • 用户名枚举防护:用户不存在时也空跑一次 bcrypt,响应时序抹平
  • 开放重定向防护:next 参数白名单校验(拒绝 \%2F%2F、控制字符)
  • Host 伪造防护:80 跳转目标固定用 MCP_GATEWAY_PUBLIC_HOST,不反射请求 Host
  • Cookie 畸形编码容错:不会因一条坏 Cookie 让整个站点 500
  • CSRF 防护:登录/配置表单 double-submit token(Cookie + 隐藏域恒定时间比对,无 token 403)
  • 真实状态码:凭据错误 401、锁定 429(不再统一 200 吞错)
  • 代理层防嵌框:dsh 应用响应补 X-Frame-Options: SAMEORIGIN + frame-ancestors 'self'

License

BSD 3-Clause © 2026 slywalker2006——自由使用、修改、分发,保留版权声明即可。

本项目是 dsh 的独立扩展,与 DeepSeek 无隶属关系。dsh 本身按它自己的许可证(MIT)授权。

内容来自项目 README(GitHub)↗

链接

同类插件

查看整个分类 →