npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@greenonion/dsh-remote-access

v0.2.0

Published

DSH web plugin for LAN, Tailscale, and Cloudflare Tunnel remote access through Caddy with API access policies.

Readme

dsh-remote-access

DSH Web 插件,为本地 DSH 提供局域网访问、Tailscale 私有远程入口和可选 Cloudflare Tunnel 公网入口。Tunnel-only 是匿名公网传输,不提供用户身份认证。

设计

局域网客户端 ── HTTPS:3081 ──► Caddy ──┬─ 所有页面/API/WS ─► API Gateway:3083 ─► DSH:3080
                                      └─ /ca.crt(兼容下载路径)

Tailscale ── Serve/Funnel ──► Caddy:3082 ──┬─ 所有页面/API/WS ─► API Gateway:3083 ─► DSH:3080
                                           └─ 无身份/无凭据请求拒绝

cloudflared ── Tunnel ──► CloudflareIngress:127.0.0.1:3084
                                  └─ Host/Origin (+ optional JWT) ─► API Gateway:3083 ─► DSH:3080

DSH 原始服务只监听 127.0.0.1:3080。远程流量不得绕过 API Gateway;网关统一处理 Host、Origin、WebSocket、API 策略和上游 loopback 规范化。配置、证书和运行状态保存在 DSH 数据目录。

访问模式

| 模式 | 入口 | 认证 | API 策略 | | --- | --- | --- | --- | | 本机 | 127.0.0.1:3080 | DSH 自身 | 完整权限 | | LAN trusted-lan | https://<LAN_IP>:3081 | 用户明确选择无认证 | lan | | LAN protected-lan | https://<LAN_IP>:3081 | Basic Auth | lan | | Tailscale Serve | Tailscale 域名 | tailnet policy,可选 Basic Auth | serve | | Tailscale Funnel | 公网 Tailscale 域名 | 强制 Basic Auth | funnel,仅基础 API | | Cloudflare Tunnel | 外部 cloudflared → 插件 loopback 适配器 | 推荐 Tunnel Basic Auth;也可显式匿名或可选 Access | cloudflare |

LAN、Serve、Funnel 各自使用 API 白名单,默认只开放会话、消息、模型列表、技能列表等基础功能。设置、凭据、主机文件和模型探测等接口默认关闭。API 方法白名单不是工具能力沙箱,获得 session.prompt 的远程主体仍应视为拥有完整 DSH 控制权。LAN 可通过 lanAllowedCidrs 或本机“配置来源网段”操作进一步限制来源网段;配置了该字段后,Caddy 会拒绝不在列表中的来源,包括 /ca.crt。留空表示不增加来源 CIDR 限制,仍由绑定地址、系统防火墙和网络边界负责隔离。

设置页可以按访问模式勾选 API、配置 Basic Auth,并为 LAN / Serve 开启“允许全部 API”或“可信远程设置”;Cloudflare Tunnel Basic Auth 也在“访问控制”中单独开关。两项高权限能力不适用于 Funnel;插件自身的写操作只接受精确的本机 Host + Origin 请求,不再使用注入到页面中的 action token。状态 GET 在没有 Origin 时也只接受精确 loopback Host,以兼容浏览器同源轮询。

设置页为 Caddy 开放的每个监听端口提供独立开关:LAN HTTPS 端口与 Tailscale loopback 端口可单独关闭,Cloudflare 适配器端口也单独控制。关闭端口会从生成的 Caddyfile 中移除对应 site(或停止 Cloudflare loopback 适配器),并由 Caddy --watch 热应用,不需要停止整个反代进程;关闭最后一个 Caddy 端口时插件才会停止 Caddy。端口开关保存在 v2 状态中,重启后仍保持关闭,避免“忘关”。 风险操作(关闭 Basic Auth、切换匿名 Tunnel、开放匿名端口、重置共享凭据、保存高权限 API 策略)会先弹出确认/取消确认框;未配置访问凭据时开启 Basic Auth 会弹出只读提示并引导生成凭据。非风险操作不弹成功提示,失败仍会用窄弹窗提示。刷新按钮位于页面右上角,更新时间显示在刷新按钮左侧。提示/确认弹窗使用更高层级,不会被 API 白名单等二级窗口遮挡。访问控制卡也有凭据状态条,可直接看到共享凭据、Tunnel 凭据和 Funnel 保护是否已配置。页面左上角不再显示操作小字。 每种访问方式下方有状态条:绿点表示运行/可达,红点表示异常或配置冲突,灰点表示未运行/未启用。访问地址旁提供二维码图标;二维码由客户端内置编码器生成 SVG,不会把地址发送到外部服务。

安装

dsh plugin --profile web add @greenonion/dsh-remote-access

手动安装:

git clone <repo-url> dsh-remote-access
cd dsh-remote-access
node install.js

安装后重启 DSH,在“设置 → 远程访问”中操作 Caddy、LAN 策略和 API 策略。Tailscale 登录、Serve/Funnel 和自启动由系统客户端管理,插件只读检测状态并展示命令,不执行 tailscale up/down。设置页会额外显示 Serve 路由是否未配置、已指向插件 loopback 入口、指向其他目标或暂时无法确认;发现外部路由时不会覆盖它。Cloudflare Tunnel 卡片只控制插件自己的 loopback 适配器;Tunnel、DNS、Access Application 和策略仍由 cloudflared/Cloudflare 控制。 LAN TLS 默认使用 lanTlsMode: auto:能找到 OpenSSL 时保持旧版本地 CA 兼容路径;Windows 找不到 openssl.exe 时自动改用 Caddy tls internal,不会再因为 spawnSync openssl ENOENT 阻止启动。也可显式指定 openssl(兼容/严格模式)或 caddy-internal(完全不依赖 OpenSSL)。

Cloudflare Tunnel loopback 适配器

Tunnel 和 Access 是两套独立能力。本项目的公网访问主路径是 Cloudflare Tunnel;适配器默认关闭,启用时需要配置 HTTPS externalOrigins,并让外部 cloudflared 的 ingress 只指向 http://127.0.0.1:3084。推荐在设置页“访问控制”打开 Tunnel Basic Auth;对应配置为 cloudflare-tunnel-basic

cloudflare:
  enabled: true
  authMode: cloudflare-tunnel-basic
  listenHost: 127.0.0.1
  listenPort: 3084
  externalOrigins:
    - https://dsh.example.com
  upstreamTimeoutMs: 120000
  upstreamConnectTimeoutMs: 10000

cloudflare-tunnel-basic 会复用“访问控制”中生成的 Basic Auth 凭据,同时保护 HTTP 和事件 WebSocket;密码只在生成响应中显示一次。cloudflare-tunnel 是显式匿名模式:请求以无用户身份 principal 进入插件,API 被网关强制限制为只读集合(agentPreset.listhost.describellm.modelssession.list 等),事件流、allApis 和可信远程设置均不可用。需要更多接口时必须先开启 Tunnel Basic Auth 或改用 Access。

已有 Basic Auth 只保存 Caddy bcrypt 时,首次打开 Tunnel Basic Auth 需要重新点击一次“生成 / 重置访问凭据”,以创建本地校验值;重置会同时轮换 LAN、Serve、Funnel 和 Tunnel Basic Auth 使用的共享凭据。

首次配置可写入 profile config;已有 v2 状态中保存过 Cloudflare 选项后,状态文件优先,需从本机设置页/setCloudflare action 修改。仅有默认的空 disabled 状态不会覆盖 profile 中的显式 Cloudflare 配置。

设置页显示的 Cloudflare 地址来自 cloudflare.externalOrigins,不是从 cloudflared 自动发现的公网 hostname。请把这里配置成 Cloudflare/cloudflared 实际暴露的 HTTPS origin;本机设置页可以点击“配置公网地址”修改,每行一个 origin。保存后会更新 Host/Origin 白名单;若适配器正在运行会自动重启适配器。远程页面不会显示这些 origin。

插件不启动或停止 cloudflared,也不写入 Tunnel/DNS/Access 配置。Tunnel Basic Auth 模式先验证本地 Basic Auth,再通过 HTTPS externalOrigins、Host/Origin、请求体大小和上游超时边界进入 API Gateway;匿名模式不验证 Access JWT。上游 HTTP 无活动超时可配置为 100–600000 毫秒(默认 120 秒),WebSocket 连接握手超时可配置为 100–120000 毫秒(默认 10 秒),超时会 fail closed。适配器只监听 loopback,外部公网暴露、域名和 Cloudflare policy 由用户自行决定。

如需使用 Access,可将 authMode 改为 cloudflare-access,再配置 HTTPS issuer 与 Access audience;该模式保留用于兼容和纵深防御,但不属于 Tunnel-only 的默认验收范围。

外部 E2E 只读诊断

安装包附带 scripts/edge-diagnostics.mjs。它只执行 HTTPS GET、tailscale statustailscale serve statustailscale funnel status,不会登录、创建、修改或停止任何 Tunnel/Serve/Funnel。Tunnel-only 探测不需要 JWT;只有选择可选 Access 模式时才通过环境变量传入短期 JWT,结果会去除 query、响应体、Serve target 和凭据:

$env:DSH_REMOTE_URL = 'https://dsh.example.com/api/session.list'
node scripts/edge-diagnostics.mjs --tailscale --json

只检查本机 Tailscale 状态时无需公网 URL:

node scripts/edge-diagnostics.mjs --tailscale --json

诊断结果会区分 edge-login-requirededge-challengeorigin-auth-requiredorigin-unavailableorigin-ok 等状态。没有测试账号或公网入口时,也可以只运行 --tailscale,不会产生外部副作用。

公网链路较慢时可用 --timeout-ms 10000 调整单次探测超时(范围 100–30000 毫秒);超出范围会直接拒绝,不会发起请求。

运行环境

  • Node.js >=20
  • Caddy 2.8+
  • OpenSSL(可选;lanTlsMode: auto 未找到时使用 Caddy internal CA,显式 openssl 模式才要求它;Windows 可通过 OPENSSL_BIN 指定 openssl.exe 的绝对路径)
  • Tailscale(使用 Serve / Funnel 时需要)

核心功能支持 Linux、macOS 和 Windows;证书安装提示使用 mDNS 检测,在 Linux 和 macOS 上启用。默认端口为 LAN 3081、Tailscale 3082、API Gateway 3083、Cloudflare loopback 3084,可在 cordis.patch.yml 中调整。

如果新版 DSH profile 同时启用了 dsh-pocket,它默认也会监听 3081。插件不会停止或覆盖该 listener;启动前会检测到端口冲突并 fail closed,在页面和 action 响应中提示用户为其中一个组件选择空闲端口。测试/迁移时可把 dsh-pocket 改到例如 3091,再让本插件继续使用 3081

运行时目录默认为 ~/.dsh/dsh-remote-access/,可用 DSH_HOME 更改,主要包含动态生成的 Caddyfile、证书、认证信息和运行日志。POSIX 使用 0700/0600;Windows 会关闭继承并用当前用户 SID + SYSTEM 的显式 DACL 保护目录、配置、认证信息和私钥。Caddy internal CA 的根证书路径由插件独立的 XDG_DATA_HOME 管理,不会读取用户全局 Caddy 数据。

LAN TLS 选择

lanTlsMode 可在 cordis.patch.yml 的插件配置中设置:

  • auto(默认):探测 OpenSSL;探测失败时回退 caddy-internal
  • openssl:只使用旧版本地 CA 生成器;缺少 OpenSSL 时返回可操作的 OPENSSL_BIN 诊断。
  • caddy-internal:由 Caddy 生成本机 CA 和叶证书,不调用 OpenSSL。Caddy 可能在首次启动时将本机根证书安装到当前 Windows 用户的信任存储;如果不希望有这个系统级副作用,请使用 openssl 模式并手动安装 /ca.crt

安全边界

  • 远程请求先经过 Caddy 和 API Gateway,未知 API 默认拒绝;页面、API 和 WebSocket 不再旁路到 DSH,本机 loopback 保留 DSH 完整权限。

  • API Gateway 的 loopback hop 使用每次进程启动生成的未持久化共享密钥;仅伪造 X-DSH-Access-Mode 的本机请求不会被当作受信入口,密钥不会出现在状态、日志或 DSH 上游。

  • 网关转发前会移除客户端提供的 ForwardedX-Forwarded-*CF-*Tailscale-*X-DSH-*Authorization 身份头,并重写上游 Host/Origin。

  • Cloudflare 适配器在网关之前完成 Tunnel Host/Origin 边界;Tunnel Basic Auth 请求先验证插件凭据,匿名 Tunnel 请求使用无用户身份的 transport principal,Access 模式额外验证 JWT。三种模式都只把受控 mode/subject 摘要放在适配器到网关的 loopback hop,JWT、CF-* 和客户端身份头不会到达 DSH。

  • LAN trusted-lan 可以不启用 Basic Auth,但同网段设备拥有完整控制权;公网入口默认应使用强认证。若显式选择 Cloudflare Tunnel-only,则它是匿名公网传输,必须依赖 API allowlist 和外部网络策略,不能视为身份认证。

  • Tailscale 生命周期由用户和系统客户端管理;插件不关闭用户已有的 Tailscale 连接或修改全局 Serve 配置。

  • Caddy 使用插件独立的配置和 PID;关闭时只停止插件创建或确认属于插件的 Caddy 资源。

  • Caddy 以 --watch 运行,只监视插件私有目录中经过校验、原子替换的 Caddyfile;不开放 Caddy admin API。端口开关通过重写 Caddyfile 由 Caddy 热应用。

  • Caddy 仍只保存 bcrypt hash;Tunnel Basic Auth 另保存不可逆的 scrypt 派生校验值,不保存明文密码。/ca.crt 用于设备安装本地 CA,保持免认证访问。

开发状态

已完成第一批安全基础:

  • 删除页面 action token。

  • 管理接口增加精确 loopback Host/Origin 校验。

  • API POST 和 WebSocket 增加跨站 Origin 拒绝。

  • 入口身份头不会转发到 DSH。

  • v2 网关为 LAN、Tailscale、Funnel 和 Cloudflare 入口生成统一的进程内 Principal;身份上下文不进入 DSH 上游、状态文件或日志。

  • LAN ingress adapter 只允许私有/链路本地地址,拒绝公网或通配绑定;显式 CIDR 限制由 Caddy 在入口处执行。

  • 页面/API/WS 统一经过 API Gateway。

  • LAN 配置迁移为 trusted-lan / protected-lan

  • Cloudflare Tunnel loopback 适配器已接入:固定 loopback 监听、Tunnel Basic Auth/显式匿名 Tunnel/可选 Access JWT 模式、Origin allowlist、HTTP/WS 代理、请求体限制和远程状态脱敏;Tunnel/DNS/Access 生命周期仍由外部 cloudflared 管理。

  • Cloudflare 适配器的上游 HTTP/WS 超时已经进入 profile/state/status 模型,设置页会显示当前值;非法值会回退到安全默认值,运行中的适配器配置变更会先停止旧 listener 再应用。

  • 匿名 Cloudflare Tunnel 的 API 被网关强制为只读集合;事件流、allApis 和可信远程设置必须启用 Tunnel Basic Auth 或 Access 后才可用。设置页风险操作统一改为确认弹窗。

  • 兼容新版 DSH client-modules:客户端 bundle 使用 npm 包名 @greenonion/dsh-remote-access 作为 ModuleLoader 注册 ID。

v2 已开始落地:state-store.js 负责 schema v2 入口状态、0.1.x 平面状态迁移、迁移前备份以及临时文件 + fsync + 原子替换;运行时已接入该状态层,识别到旧状态后会自动备份并转换,非法 JSON 不会被覆盖。当前切片不改变现有监听器拓扑,Tailscale/Cloudflare 状态只保留配置且不会被旧运行时自动启用。

正在开发:真实 tailnet/Cloudflare 外部入口和 cloudflared 故障恢复验证。Windows ACL、Caddy internal 无 OpenSSL LAN 路径、Tailscale 只读入口适配器、Cloudflare loopback 适配器已接入运行时状态和设置页;本地 Tunnel-only HTTP/WSS 与 RSA JWT → Cloudflare verifier → adapter → API Gateway 链路已覆盖。当前测试套件在受支持环境中全部通过。

License

MIT