dsh-vpn
Verifieddsh-vpn · v0.1.3 · MIT · Web UI
DeepSeek Harness plugin: one-click sing-box deployment to a VPS over SSH, with a settings page and QR codes
Install
dsh plugin add dsh-vpn Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
- github/aicivilization/dsh-vpn 0 0 archived
Tags
Readme
dsh-vpn
DeepSeek Harness 插件:在 dsh 里填好 VPS 的 IP、端口、用户名和密码,一键部署 sing-box,然后扫二维码导入代理客户端。
- 不依赖本机的 ssh 命令:内置纯 JS 的 SSH 客户端(ssh2),用密码登录。
- 两种用法:在设置页点按钮,或者直接对 agent 说“帮我装个节点”。
- 五种协议可选:VLESS Reality、Hysteria2(默认)、TUIC v5、AnyTLS、Shadowsocks 2022。
- 免域名的正规证书:可选 Let's Encrypt 为服务器 IP 签发的证书,所有客户端都能正常校验证书。
使用
用你启动 dsh 的同一种方式安装。profile 名就是启动 dsh 时 --profile 后面的名字;用 dsh web 启动的话就是 web:
# 用 npx 运行 dsh 的
npx @deepseek-ai/dsh plugin --profile web add dsh-vpn
# 全局安装了 dsh 的
dsh plugin --profile web add dsh-vpn
装好后重启 dsh,点左下角「设置」,左侧菜单里的「VPN 设置」就是本插件的设置页(dsh 0.1.5 和 0.1.7 相同)。
在 VPN 设置里:
- 填写服务器 IP、SSH 端口、用户名、密码,点「保存」和「测试连接」。
- 勾选要安装的协议,选择证书类型(推荐「IP 证书」),保存后点「安装 / 更新」。
- 在「节点二维码」里点「刷新二维码」,用手机或电脑上的客户端扫码导入。
- 服务器防火墙的端口由插件自动放行,不用手动操作;安装完成后提示框会列出放行了哪些端口。
防火墙
安装时插件会检测 VPS 上启用的防火墙,自动放行所选协议的端口(使用 IP 证书时还有 TCP 80):
| 防火墙 | 做法 |
|---|---|
| ufw | ufw allow |
| firewalld | 放行端口(永久规则和运行时规则都加) |
| iptables(如 Oracle Cloud 镜像自带的 REJECT 规则) | 在 INPUT 链最前面插入放行规则,带 dsh-vpn 标签 |
| nftables(原生规则集) | 在各个 input 链插入放行规则,带 dsh-vpn 标签 |
| 没有启用防火墙 | 不做任何改动 |
- 规则写在
/etc/dsh-vpn/firewall.sh里,服务每次启动都会重新应用,所以 iptables/nftables 规则重启后也还在。 - 重新安装时,先关闭上次放行的端口,再放行新的,所以取消勾选的协议端口会被关掉。卸载时会删除插件添加的所有规则。
- 插件只添加和删除自己的规则,从不启用防火墙、修改默认策略或改动 SSH 端口。
- 云服务商的安全组(阿里云、腾讯云、AWS 等)在服务器外部,只能在服务商控制台修改,插件改不了;如果有安全组,仍需在控制台放行同样的端口。
证书
| 类型 | 适合 | 客户端校验 |
|---|---|---|
| 自签证书(默认) | 不想开放 80 端口 | Hysteria2 锁定证书指纹;TUIC 和 AnyTLS 的链接无法锁定,客户端会跳过校验 |
| IP 证书(推荐) | 大多数情况 | 所有协议都正常校验证书,不需要域名 |
IP 证书由 sing-box 1.14 内置的 ACME 向 Let's Encrypt 申请(2026 年起正式提供),通过 80 端口完成 HTTP 验证。证书有效期 6 天,由 sing-box 自动续期。
- 签发失败(常见原因是 80 端口没开):自动退回自签证书,节点仍可使用,页面会提示原因。
- 80 端口被其他程序占用:直接拒绝,不改动正在运行的节点。
- 「查看状态」会显示证书剩余时间;剩余不到 24 小时仍未续期时会发出警告,因为证书过期后客户端将无法连接。
安全设计
| 方面 | 做法 |
|---|---|
| 密码存储 | 存在 dsh 凭据库($DSH_HOME/.credentials.yaml,权限 0600),不写进配置文件;浏览器只能写入,读不回来 |
| 接口鉴权 | 设置页的接口挂在 dsh 自己的 /api 下,复用 dsh 的登录 cookie 和防跨站、防 DNS rebinding 检查 |
| 主机指纹 | 首次连接时记录 SSH 主机指纹,之后指纹变化就拒绝连接,防止中间人截获密码 |
| sudo | 非 root 用户用 sudo -S:密码只经 stdin 传入,不会出现在命令行,也不会传给脚本 |
| agent 操作 | agent 安装或卸载前会弹出审批,提示语言跟随电脑系统语言,并写明目标服务器、协议,以及是否重新生成密钥 |
| 证书 | 推荐用 IP 证书,所有协议都正常校验;自签模式下 Hysteria2 锁定指纹,TUIC 和 AnyTLS 会标注“需跳过证书校验” |
组成
| 路径 | 作用 |
|---|---|
scripts/vpn.sh |
在服务器上运行的安装脚本,也可以单独使用:ssh vps 'sudo bash -s -- install --protocols reality,hy2' < scripts/vpn.sh |
src/ssh.ts / src/remote.ts |
SSH 连接、主机指纹锁定、上传并执行脚本 |
src/core.ts |
统一的操作入口(设置页和 agent 共用),同一时间只执行一个操作 |
src/settings.ts / src/credential-store.ts |
服务器设置的校验和存储 |
src/api.ts |
设置页调用的 /api/dsh-vpn/* 接口 |
src/index.ts |
agent 工具 vpn_install / vpn_status / vpn_links / vpn_uninstall,以及执行前的审批 |
src/client/ |
浏览器端:设置弹窗里的「VPN 设置」一栏、二维码 |
src/skill.ts + assets/vpn-ops.md |
vpn-ops 技能:操作流程和排障 |
远端落盘位置
/usr/local/bin/sing-box/etc/dsh-vpn/:state.env(密钥、端口、已选协议、证书类型)、config.json、cert/(自签证书)、acme/(IP 证书,由 sing-box 维护)/etc/systemd/system/dsh-vpn.service/etc/sysctl.d/99-dsh-vpn.conf:开启 BBR
开发与测试
pnpm install
pnpm test # 单元测试(进程内的假 SSH 服务器,不联网)
pnpm build # lib/:宿主端 tsc 转译 + 浏览器端 esbuild 打包
DSH_SRC=/path/to/deepseek-harness pnpm typecheck # 对照 dsh 源码做宿主端和浏览器端的类型检查
build 用 esbuild 把 ssh2 打包进 lib/,所以发布到 npm 的包没有任何运行时依赖,也就没有安装脚本。这是必须的:dsh 自带的 pnpm 11 在依赖的安装脚本被跳过时会让 dsh plugin add 直接失败。被打包的第三方库的许可证见 THIRD_PARTY_NOTICES.md。
npm 上的 @deepseek-ai/* 包版本过旧,所以 build 不做类型检查,类型检查对照 dsh 源码单独进行。
发布
推送与 package.json 版本号一致的标签,GitHub Actions 会先跑测试,再发布到 npm。需要在仓库 Secrets 里配置 NPM_TOKEN。仓库是私有的,npm 不支持为私有仓库生成来源证明(provenance),所以发布时不带来源证明:
git tag v0.1.0 && git push origin v0.1.0
端到端测试会在目标机器上安装再卸载,并用 sing-box 客户端实测每种协议的连通性。本地可以用 Lima 虚拟机:
limactl start --name=vps --vm-type=vz --network=vzNAT --set '.mounts=[]' template:ubuntu-24.04
# 在虚拟机里开启 sshd 的密码登录并设置密码,然后:
DSH_VPN_E2E_HOST=192.168.64.2 DSH_VPN_E2E_USER=root DSH_VPN_E2E_PASSWORD=… pnpm test:e2e
防火墙测试会依次启用 ufw、firewalld、iptables、nftables,只能在测试虚拟机上运行:
DSH_VPN_E2E_FIREWALL=1 DSH_VPN_E2E_HOST=… DSH_VPN_E2E_USER=root DSH_VPN_E2E_PASSWORD=… pnpm test:e2e
IP 证书的测试需要一个本地 ACME 服务器,用 Let's Encrypt 官方的 Pebble 模拟。只能在测试虚拟机上运行,因为它会把 Pebble 的根证书加入系统信任:
ssh 测试机 'sudo bash -s' < tests/e2e/pebble-setup.sh
DSH_VPN_E2E_ACME=https://localhost:14000/dir DSH_VPN_E2E_HOST=… pnpm test:e2e
在插件配置里设置 acmeProvider,就可以让插件改用 Pebble 或其他 ACME 服务器。
TODO
- SSH 私钥登录
- 导出客户端配置文件(sing-box / mihomo)和订阅链接
- 可自定义 Reality 的 SNI、协议端口
- 证书使用自己的域名(DNS 验证:Cloudflare / 阿里云)
- IPv6 的 IP 证书(目前只在 IPv4 上验证过)
- 支持 OpenRC(Alpine)
- 支持 GitHub 下载镜像
- 在真实 VPS 上跑端到端测试(Debian 12 / Ubuntu 24.04 / Rocky 9)