From 0c5502147958e1365aacf58ee66e2ba0786c909a Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 12 Oct 2026 00:19:04 +0800 Subject: [PATCH] =?UTF-8?q?fix(origin):=20Origin=20=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=E4=B8=BA=20https://3dtank.com=20=E5=B9=B6=E5=9B=9E=E9=80=80?= =?UTF-8?q?=E8=AF=AF=E6=94=B9=E7=9A=84=20c2=20=E4=B8=8A=E6=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 中继/代理 origin 由 https://3dtank.com/play/ 改为 https://3dtank.com(Origin 规范只到源、不带路径);referer 保持完整地址 https://3dtank.com/play/ - 上游与 /config.xml 回源回退到 c1.3dtank.com:9090:战斗必须连 c1,改 c2 会让前端战斗连 c2 而无法使用 - wss_server.js 新增「上游握手头」诊断日志,区分「浏览器→中继」与「中继→上游」两段 - README 同步 --- 3DTank/README.md | 5 +++-- 3DTank/Start-LocalAndRelay.ps1 | 2 +- 3DTank/tools/serve.js | 3 ++- 3DTank/tools/wss_server.js | 15 +++++++++++++-- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/3DTank/README.md b/3DTank/README.md index c7d2da7..dd3f8df 100644 --- a/3DTank/README.md +++ b/3DTank/README.md @@ -86,10 +86,11 @@ config-template = http(s)://<本机>/config.xml | 本机路径 | 转发到 | 说明 | |---|---|---| | `/resources/**` | `https://res.3dtank.com/**` | CDN 资源基址 | -| `/config.xml` | `https://c1.3dtank.com/config.xml` | 服务器配置(指向 `wss://c1.3dtank.com:9090`) | +| `/config.xml` | `https://c1.3dtank.com/config.xml` | 服务器配置(指向 `wss://c1.3dtank.com:9090`;开始战斗必须连 c1) | | `/s/status.js` | `https://3dtank.com/s/status.js` | balancer 节点状态 | -代理会强制带上 `origin: https://3dtank.com` 与 `referer`(CDN 有来源校验),并落盘缓存。 +代理会强制带上 `origin: https://3dtank.com`(Origin 按规范只到源、不带路径)与 +`referer: https://3dtank.com/play/`(Referer 才是完整地址),并落盘缓存。 另外 URL 查询参数优先级高于上述默认值,也可用 `?resources=…&config-template=…&balancer=…` 直接覆盖(值需 URL 编码)。 diff --git a/3DTank/Start-LocalAndRelay.ps1 b/3DTank/Start-LocalAndRelay.ps1 index 7a60c17..bda447c 100644 --- a/3DTank/Start-LocalAndRelay.ps1 +++ b/3DTank/Start-LocalAndRelay.ps1 @@ -26,7 +26,7 @@ param( [int]$MirrorPort = 8080, [int]$RelayPort = 9091, - [string]$Upstream = 'wss://c1.3dtank.com:9090/', + [string]$Upstream = 'wss://c1.3dtank.com:9090/', # 战斗要连 c1(c2 只用于其它阶段) [string]$Label = (Get-Date -Format 'yyyyMMdd-HHmmss'), [switch]$FetchAssets, # 先跑 fetch_assets.js 镜像资源(首次或资源缺失时用) [switch]$KillExisting, # 端口被占用时,先结束占用进程 diff --git a/3DTank/tools/serve.js b/3DTank/tools/serve.js index 25d2519..e00b4f1 100644 --- a/3DTank/tools/serve.js +++ b/3DTank/tools/serve.js @@ -42,11 +42,12 @@ const PROXY = [ { Prefix: '/config.xml', Target: 'https://c1.3dtank.com', StripPrefix: false, KeepQuery: false }, { Prefix: '/s/', Target: 'https://3dtank.com', StripPrefix: false, KeepQuery: false }, ]; +// 代理回源头:Origin 按规范只到源(不带路径),Referer 才是完整地址 const UPSTREAM_HEADERS = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/152.0.0.0 Safari/537.36 Edg/152.0.0.0', 'accept-language': 'zh-CN,zh;q=0.9,en-GB;q=0.8,en;q=0.7,en-US;q=0.6', - origin: 'https://3dtank.com/play/', + origin: 'https://3dtank.com', referer: 'https://3dtank.com/play/', }; diff --git a/3DTank/tools/wss_server.js b/3DTank/tools/wss_server.js index 1d46c78..4ccabac 100644 --- a/3DTank/tools/wss_server.js +++ b/3DTank/tools/wss_server.js @@ -40,7 +40,7 @@ const Arg = (Name, Def) => { }; const PORT = Number(Arg('port', '9091')); -const UPSTREAM = Arg('upstream', 'wss://c1.3dtank.com:9090/'); +const UPSTREAM = Arg('upstream', 'wss://c1.3dtank.com:9090/'); // 注意:开始战斗要连 c1,别改成 c2(c2 只用于其它阶段) const LABEL = Arg('label', new Date().toISOString().replace(/[:.]/g, '-')); const PACKET_DIR = path.resolve(Arg('dir', path.join(PROJECT, 'packets', LABEL))); @@ -91,10 +91,13 @@ function RequireWs() { const Ws = RequireWs(); // 上游握手头:真实服务器会校验来源 +// 注意 Origin 与 Referer 的差别(对齐真实浏览器在 https://3dtank.com/play/ 下的行为): +// Origin 按规范**只到源**,不带路径 → https://3dtank.com +// Referer 是完整地址,带路径 → https://3dtank.com/play/ const UPSTREAM_HEADERS = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/152.0.0.0 Safari/537.36 Edg/152.0.0.0', - origin: 'https://3dtank.com/play/', + origin: 'https://3dtank.com', referer: 'https://3dtank.com/play/', }; @@ -534,6 +537,14 @@ WsServer.on('connection', (Client, Req) => { // 真实服务器会据此校验来源,必须覆盖,不能透传。 UpHeaders['origin'] = UPSTREAM_HEADERS.origin; UpHeaders['referer'] = UPSTREAM_HEADERS.referer; + // 诊断:打印**发往上游**的真实握手来源(注意与上面「来源: … Origin: …」那行区分开 —— + // DevTools 里看到的本机 Origin 是「浏览器→中继」这一段,页面 JS 改不了;中继改的是「中继→上游」这一段) + State.Log( + '上游握手头: origin=' + UpHeaders['origin'] + + ' referer=' + UpHeaders['referer'] + + ' user-agent=' + String(UpHeaders['user-agent'] || '').slice(0, 48) + '…' + + ' cookie=' + (UpHeaders['cookie'] ? '有(' + UpHeaders['cookie'].length + 'B)' : '无'), + ); const ClientProto = Req.headers['sec-websocket-protocol']; const UpProtocols = ClientProto ? String(ClientProto).split(',').map(function (S) { return S.trim(); }).filter(Boolean)