0
0
0

容器与部署类

文章摘要
|

来源:intranet-tunnel/docs/AGENTS-ARCHIVE.md## 服务端服务全面检查(2026-09-12 实操)(原文 3081 字符)

服务端服务全面检查(2026-09-12 实操)

不用登面板点页面,直接走 API 更完整、可脚本化。脚本: H:\Works\.recover\check-services.js(20 项)/ check-errorlogs.js(追查遗留项)。

公开端点(无需认证,先跑这些)

curl.exe --noproxy '*' -4 -sk https://tunnel.sushike.cloud/healthz
# {"database":"ok","online":1,"port_pool_min":48081,"port_pool_max":48100,"status":"ok","uptime":"…","version":"1.0.0"}
curl.exe --noproxy '*' -4 -sk https://tunnel.sushike.cloud/api/auth/config
# 登录页用的公开配置:captcha_enabled / sms_login / email_login 等

/healthzonline 就是当前在线客户端数,能一眼看出客户端是否连上。

认证端点的 20 项检查清单

登录 POST /api/auth/login{"username":"admin","password":…})拿 token 后逐项 GET:

/api/auth/me          /api/overview        /api/clients         /api/tunnels
/api/stats?window=1h  /api/ddns            /api/ddns/status     /api/proxies
/api/certs            /api/certs/status    /api/forwards        /api/forwards/stats
/api/logs/stats       /api/logs/files      /api/sms/stats       /api/email/status
/api/alert/status     /api/backup/status   /api/backup/history  /api/settings

密码不要写进脚本,从容器环境变量取(不回显):

$envDump = & workbench exec -i <inst> -c "docker inspect tunnel-server --format '{{range .Config.Env}}{{println .}}{{end}}'"
$env:ADMIN_PW = ($envDump | Where-Object { $_ -like 'ADMIN_PASSWORD=*' } | Select-Object -First 1).Substring(17)
node check-services.js

Node 的 fetch 而不是 curl + PowerShell:免去转义问题,且能直接读 JSON 判断成败。 Node 的 fetch 不读系统代理,所以访问公网面板无需额外处理。

⚠️ using_default_credentials 不是「密码仍是默认值」

这个字段只判断管理员用户名是否仍为 admin,与密码无关:

defaultAdmin := h.cfg.Security.DefaultAdminUsername == "admin" || h.cfg.Security.DefaultAdminUsername == ""
usingDefaultCred := defaultAdmin && !h.settings.GetBool(model.SettingAuthDefaultCheckOff, false)

所以 true 很常见,不要当成弱口令告警。要消除提示就改 AUTH_DEFAULT_USERNAME, 或把 auth.default_check_disabled 置 true。

审计日志能解释「凭据为何突然失效」

/api/logs/audit 记录了谁在何时调了什么接口。实测靠它定位到 「客户端 Token 明明验证过却登录被拒」的原因:

16:03:06  POST /api/clients           ← 创建客户端 pc1
16:43:41  POST /api/clients/5/token   ← 之后又重置了 Token

照此推断:凡是「之前验证通过的凭据后来失效」,先去审计日志找 /token/password 之类的重置动作,别急着怀疑配置或哈希算法。

ERROR 日志排障要先看时间戳

实测 4 条 ERROR 全是历史遗留、且都已修复,不是当前故障

时间消息结论
15:33:52/53DNS 服务商热更新失败,仍使用原配置DDNS 未启用时产生
15:54:18内置反向代理启动失败1.0.1 初版的 48080 争抢,换第二版后消失
15:56:18注册隧道路由失败域名唯一索引冲突

判据/api/logs/statsprogram_by_level 给出各级别条数, 再按 level=ERROR 拉明细比对时间戳 —— 先确认是不是本次操作之后产生的

临时关闭图形验证码做检查(务必恢复)

captcha_enabled=true 时脚本化登录过不去。做法(已验证):

sed -i 's/^AUTH_CAPTCHA_ENABLED=.*/AUTH_CAPTCHA_ENABLED=false/' .env
docker compose up -d --force-recreate tunnel-server   # restart 不重读 env_file
# ... 检查 ...
sed -i 's/^AUTH_CAPTCHA_ENABLED=.*/AUTH_CAPTCHA_ENABLED=true/' .env
docker compose up -d --force-recreate tunnel-server
  • 改回原值而不是删键:该键本来就在 .env 里(第 50 行左右)。
  • 改前备份.env.bak.captcha-check.<时间戳>
  • 验证还原ls -la .env .env.bak.* 两者字节数应一致(实测 7842 == 7842),

再用 /api/auth/config 确认 captcha_enabled 回到 true。



来源:intranet-tunnel/docs/AGENTS-ARCHIVE.md### 镜像更新流程(已验证)(原文 2480 字符)

镜像更新流程(已验证)

服务器上没有源码(只有 compose、.env 与镜像 tar),部署方式是 「本地构建 → docker save → 上传 → load → 改 tag → up -d」:

# 1) 本地构建(只动 server 时增量很快)
docker build -f server/Dockerfile -t intranet-tunnel/server:1.0.1 `
  --build-arg GOPROXY=https://goproxy.cn,direct H:\Works\intranet-tunnel

# 2) 导出(单镜像 + 层去重后仅 12.6 MB)
docker save -o release/intranet-tunnel-server-1.0.1.tar intranet-tunnel/server:1.0.1

# 3) 上传(先 rm 远程同名文件,upload 有覆盖保护)
workbench upload <tar> /home/docker/intranet-tunnel/ -i i-wz9diqyfq2owhs5dn8gx

# 4) 服务器执行部署脚本(写成 .sh 上传再 sh 执行,绕开 workbench 传参坑)
docker load -i intranet-tunnel-server-1.0.1.tar
sed -i 's|intranet-tunnel/server:1.0.0|intranet-tunnel/server:1.0.1|' docker-compose.yml
docker compose up -d tunnel-server

打新 tag 而不是覆盖旧 tag1.0.0 留在本地与服务器上,出问题可立刻切回。


  • DSH 会话记录可作为源码恢复源(2026-09-12 实测,成功恢复整个项目):

项目文件被清理且无 git、无回收站条目、无卷影副本时,DSH 自己的会话记录是最后的手段。 位置:%APPDATA%\dsh-desktop\harness\sessions\<cwd转义名>\<session-id>\session.jsonl.zstd

  • 文件是多个紧邻 zstd frame 串联(增量追加)。zlib.zstdDecompressSync(整个文件) 只解第一帧

(通常只有 185 字节的会话头),必须逐帧推进:解压 buf.subarray(pos),再 buf.indexOf(MAGIC, pos+4)(MAGIC=28 b5 2f fd)作为下一帧起点。Node 的流式解压器会在第二帧 报 ZSTD_error_prefix_unknown不要用它

  • 事件为 JSONL:{"type":"tool/call","time":…,"data":{"name":"write","arguments":"{…}"}}

arguments字符串,需二次 JSON.parsewritecontenteditold_string/new_string

  • 只重放"当时成功"的操作tool/result 的文本以 Error: 开头即表示该次写入未发生

(常见于 file changed since it was read 这类守卫错误),照常重放会让状态偏离。

  • 同一会话可能被提取两次(重复文件)会导致每条 write/edit 应用两遍,症状是

method already declared / redeclared in this block。重放前务必确保每个会话只有一份事件流。

  • tool/resultread 的返回带 <path>行号内容,是独立于重放的快照,可作交叉校验;

不能用它覆盖文件(判据不可靠:结尾说明行 (End of file - total N lines)、 末尾换行等都会造成"差 1 字节"的假差异,也可能覆盖成更早的状态)。

  • 重放无法复现 pwsh 的旁路改动Move-Item/Remove-Item/git mv/Set-Content/here-string 写文件,

以及 go mod tidy 的依赖声明变更。实测缺失的 shared/muxserver/internal/appapp.goguardConfigapi/util.gomustJSON/parseIP/contextWithTimeout/decodeJSONOptional 等全部源于此。

  • PowerShell 5.1 的 Set-Content -Encoding UTF8 会写 BOM,会让 go.mod 解析失败

unexpected input character '\ufeff')。重放后必须统一清除文本文件 BOM

  • 含中文的 .ps1 必须存为 UTF-8 with BOM,否则 PS 5.1 按 ANSI 解析导致语法错误;

here-string 结束符 "@ 必须位于行首,插入代码时不要加缩进

  • 恢复脚本保留在 H:\Works\.recover\rebuild-all.ps1 为一键重建入口)。

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或者给予支持!

评论