dsh-mesh-access 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # 更新日志
2
2
 
3
+ ## 1.3.0 — 面板显示登录弹窗状态,讲清账号密码在哪改
4
+
5
+ 用户问「网页的账号密码没有配置项,我上哪知道是啥、也没法改?」——账号密码是服务器端 nginx 的 Basic 认证(`/etc/nginx/.dsh_htpasswd`),插件改不了服务器文件,但至少要把状态和操作说清楚:
6
+
7
+ - 状态区新增第四颗 pill:真实 GET 一次公网入口,`401 + WWW-Authenticate: Basic` → 「有登录弹窗(Basic)」;200/303 → 「无登录弹窗」(此时给出安全提醒:知道地址的人都能打开你的 DSH 登录页);
8
+ - 有弹窗时提示:账号密码是服务器上跑 `tools/frps-setup.sh` 时它打印给你的(默认账号 `dsh`);忘了就 `sudo htpasswd /etc/nginx/.dsh_htpasswd dsh` 重设;
9
+ - 无弹窗时提示:加登录的两条命令(同上)。
10
+
11
+ ## 1.2.1 — 表单里写清服务器端怎么装
12
+
13
+ 用户问「服务器端的 frps / nginx 是面板一键装还是让 AI 装?」——面板够不着你的服务器,写明白:
14
+
15
+ - 表单顶部直接给出两条路:把 `docs/AI-SETUP.md` 丢给 AI 让它上服务器跑 `tools/frps-setup.sh`;或者自己 SSH 上去跑同一条命令(`--domain` 连 https 一起配好);
16
+ - 没填配置时的提示改为直接指向「填服务器信息」按钮和 frps 安装命令。
17
+
18
+ 功能没有变化,只改文案。
19
+
3
20
  ## 1.2.0 — 面板里就能填服务器信息
4
21
 
5
22
  1.1.0 仍然要求你先去跑脚本写 `frpc.toml`,面板只是个看板。现在不用了:
package/lib/client.js CHANGED
@@ -274,6 +274,10 @@ window.__ModuleLoader__.load({
274
274
  tn.running ? 'frpc 运行中(本插件)' : tn.external ? 'frpc 运行中(外部进程)' : 'frpc 未运行'),
275
275
  h('span', { style: S.pill(Boolean(tn.reachable)) }, h('span', { style: S.dot(Boolean(tn.reachable)) }), tn.reachable ? '公网可达' : '公网不可达'),
276
276
  h('span', { style: S.pill(Boolean(tn.url)) }, h('span', { style: S.dot(Boolean(tn.url)) }), tn.domain ? '域名 ' + tn.domain : tn.remotePort ? '端口 ' + tn.remotePort : '未配置'),
277
+ (tn.reachable && tn.webAuth
278
+ ? h('span', { style: S.pill(tn.webAuth !== 'none') }, h('span', { style: S.dot(tn.webAuth !== 'none') }),
279
+ tn.webAuth === 'basic' ? '有登录弹窗(Basic)' : tn.webAuth === 'none' ? '无登录弹窗' : '有访问控制')
280
+ : null),
277
281
  ),
278
282
  h('div', { style: S.row, marginTop: 12 },
279
283
  h('button', {
@@ -293,7 +297,11 @@ window.__ModuleLoader__.load({
293
297
  formOpen
294
298
  ? h('div', { style: { marginTop: 12, padding: 12, borderRadius: 8, border: '1px dashed rgba(127,127,127,.35)' } },
295
299
  h('div', { style: S.hint, marginTop: 0, opacity: 0.8 },
296
- '填的是你自己的服务器。不知道填什么就问给你配服务器的那个人,或者把 docs/AI-SETUP.md 丢给你的 AI。'),
300
+ '这里填的是你自己的服务器。服务器那一头(frps + nginx + 证书)插件够不着,两个办法:'),
301
+ h('div', { style: { ...S.hint, marginTop: 6, paddingLeft: 12, opacity: 0.85 } },
302
+ '① 把服务器交给 AI:把 docs/AI-SETUP.md 一起丢给它,让它上去跑 tools/frps-setup.sh(一条命令全装好);'),
303
+ h('div', { style: { ...S.hint, marginTop: 4, paddingLeft: 12, opacity: 0.85 } },
304
+ '② 自己 SSH 上去跑:sudo ./tools/frps-setup.sh --port 7000 --http-port 21081 --domain 你的域名。域名和 https 也是这条命令带 --domain 就顺手配好的。'),
297
305
  h('div', { style: S.row, marginTop: 10, gap: 10 },
298
306
  h('div', null, h('label', { style: S.label }, '服务器地址(IP 或域名)'),
299
307
  h('input', { style: S.input, value: form.serverAddr || '', placeholder: '1.2.3.4', onChange: setField('serverAddr') })),
@@ -333,11 +341,16 @@ window.__ModuleLoader__.load({
333
341
  h('div', { style: S.hint },
334
342
  tn.configFound
335
343
  ? 'frpc 配置:' + tn.configPath + (tn.serverAddr ? '(' + tn.serverAddr + ',本地 ' + tn.localPort + ' → 远端 ' + tn.remotePort + ')' : '')
336
- : '没找到 frpc 配置 ' + (tn.configPath || '') + '。这条是可选的:用你自己的服务器做公网入口,就不受组网中继心跳超时的影响。装法见 docs/VPS.md,或者把 docs/AI-SETUP.md 丢给你的 AI 让它跑 tools/frps-setup.sh + tools/frpc-setup.sh。',
344
+ : '还没填服务器信息(点上面的「填服务器信息」)。服务器那头先装 frps:sudo ./tools/frps-setup.sh,想连域名 https 一起配就加 --domain 你的域名 —— 这一步在服务器上跑,面板替不了;本机这头填完表单保存就行。',
337
345
  tn.external && !tn.running
338
346
  ? ' 现在这个隧道是你自己的外部进程在跑(多半是 systemd 单元 dsh-frpc),所以这里显示为「外部进程」并且不让重复启动,免得抢同一个 remotePort。想停:systemctl --user stop dsh-frpc。'
339
347
  : '',
340
348
  ' 组网走中继时 RTT 800–990 ms(最坏 3.7 s),长连接会被心跳判死;你自己的服务器通常 30–60 ms。',
349
+ tn.reachable && tn.webAuth === 'none'
350
+ ? ' 注意:这个入口现在没有登录弹窗,知道地址的人都能打开你的 DSH 登录页。给入口加登录:SSH 到服务器跑 tools/frps-setup.sh --domain 你的域名(会生成随机账号密码并打印出来);已有账号想改密码:sudo htpasswd /etc/nginx/.dsh_htpasswd dsh。账号密码是服务器端的东西,面板这里只负责告诉你状态,改要上服务器。'
351
+ : tn.webAuth === 'basic'
352
+ ? ' 打开地址时浏览器会先弹账号密码框(nginx Basic 认证)。账号密码是你在服务器上跑 tools/frps-setup.sh 时它打印给你的(默认账号 dsh);忘了就上服务器 sudo htpasswd /etc/nginx/.dsh_htpasswd dsh 重设。'
353
+ : '',
341
354
  ),
342
355
  tn.log && tn.log.length
343
356
  ? h('div', { style: { ...S.hint, ...S.mono, marginTop: 8, whiteSpace: 'pre-wrap', opacity: 0.5 } }, tn.log.slice(-4).join('\n'))
package/lib/index.js CHANGED
@@ -627,8 +627,18 @@ transport.useEncryption = true
627
627
  const port = t.domain ? 443 : t.remotePort
628
628
  const snap = tunnelSnapshot()
629
629
  const reachable = await probe(host, port)
630
+ let webAuth = null
631
+ if (reachable) {
632
+ try {
633
+ const r = await fetch(`${t.domain ? 'https' : 'http'}://${host}${t.domain ? '' : ':' + t.remotePort}/`, { redirect: 'manual', signal: AbortSignal.timeout(4000) })
634
+ const www = r.headers.get('www-authenticate') || ''
635
+ if (r.status === 401 && /basic/i.test(www)) webAuth = 'basic'
636
+ else if (r.status === 401 || r.status === 403) webAuth = 'other'
637
+ else webAuth = 'none'
638
+ } catch { webAuth = null }
639
+ }
630
640
  // external:公网已经通了,但 frpc 不是这个进程拉起来的(用户自己的 systemd 单元在跑)
631
- return json(res, 200, { ok: true, ...snap, reachable, external: reachable && !snap.running })
641
+ return json(res, 200, { ok: true, ...snap, reachable, webAuth, external: reachable && !snap.running })
632
642
  }
633
643
  if (req.method !== 'POST') return json(res, 405, { ok: false, error: 'GET or POST only' })
634
644
  let body = {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-mesh-access",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Control your DSH from your phone: opens a port on the mesh/VPN interface from inside the running server process, so a phone browser gets the same instance and the same session list — no SSH, no second dsh. Also reachable from another PC, a GUI NAS, or a TV box.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",