From 8c7f87b58fd7ece76a6db3dc47357ea87e499c8f Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sun, 11 Oct 2026 19:54:22 +0800 Subject: [PATCH] =?UTF-8?q?fix(relay):=20=E4=B8=8A=E6=B8=B8=E6=8F=A1?= =?UTF-8?q?=E6=89=8B=E6=95=B4=E5=8C=85=E9=80=8F=E4=BC=A0=E5=AE=A2=E6=88=B7?= =?UTF-8?q?=E7=AB=AF=E8=AF=B7=E6=B1=82=E5=A4=B4=E5=B9=B6=E9=95=9C=E5=83=8F?= =?UTF-8?q?=E5=AD=90=E5=8D=8F=E8=AE=AE=EF=BC=8C=E5=AF=B9=E9=BD=90=E6=B5=8F?= =?UTF-8?q?=E8=A7=88=E5=99=A8=E7=9B=B4=E8=BF=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 除 Host/Connection/Upgrade/Sec-WebSocket-* 外,客户端握手头全部原样带上(Cookie / Origin / User-Agent / Referer / Accept-Language / Sec-Fetch-* 等) - Sec-WebSocket-Protocol 改走 ws 的 protocols 选项,由 ws 负责协商校验 --- 3DTank/tools/wss_server.js | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/3DTank/tools/wss_server.js b/3DTank/tools/wss_server.js index 1d76140..9d25199 100644 --- a/3DTank/tools/wss_server.js +++ b/3DTank/tools/wss_server.js @@ -511,17 +511,27 @@ WsServer.on('connection', (Client, Req) => { let Upstream = null; const Pending = []; // 上游未就绪时暂存竞态帧(握手帧常比上游 TLS 建连更早到达),一连上立即按原序补发 - // 握手头:把客户端**真实的** Origin / User-Agent / Referer 透传给上游(与浏览器直连时一致)。 - // 不能用写死的 origin:真实服务器可能按 Origin 选择构建/配置,写死会让响应与本地构建对不上, - // 表现为客户端握手失败自行断开(close code 1005)。 - const UpHeaders = { - 'user-agent': Req.headers['user-agent'] || UPSTREAM_HEADERS['user-agent'], - origin: Req.headers['origin'] || UPSTREAM_HEADERS.origin, - referer: Req.headers['referer'] || UPSTREAM_HEADERS.referer, - }; + // 握手头:把客户端**真实**的握手请求头整包透传给上游(Cookie / Origin / User-Agent / Referer / + // Accept-Language / Sec-Fetch-* …),让上游看到的握手与「浏览器直连」完全一致。 + // 仅排除必须由 ws 自己生成/协商的:Host / Connection / Upgrade / Sec-WebSocket-* + // (其中子协议改走 protocols 选项,由 ws 负责协商与校验)。 + const UpHeaders = {}; + for (const K of Object.keys(Req.headers)) { + const L = K.toLowerCase(); + if (L === 'host' || L === 'connection' || L === 'upgrade') continue; + if (L.indexOf('sec-websocket-') === 0) continue; + UpHeaders[L] = Req.headers[K]; + } + if (!UpHeaders['user-agent']) UpHeaders['user-agent'] = UPSTREAM_HEADERS['user-agent']; + if (!UpHeaders['origin']) UpHeaders['origin'] = UPSTREAM_HEADERS.origin; + if (!UpHeaders['referer']) UpHeaders['referer'] = UPSTREAM_HEADERS.referer; + const ClientProto = Req.headers['sec-websocket-protocol']; + const UpProtocols = ClientProto + ? String(ClientProto).split(',').map(function (S) { return S.trim(); }).filter(Boolean) + : undefined; // 转发:客户端帧**原样直发**;上游未就绪时暂存,open 后按原序补发(不重放、不改字节)。 - Upstream = new Ws(UPSTREAM, { headers: UpHeaders, rejectUnauthorized: false }); + Upstream = new Ws(UPSTREAM, { headers: UpHeaders, protocols: UpProtocols, rejectUnauthorized: false }); Upstream.binaryType = 'nodebuffer'; Upstream.on('open', () => { State.Log('上游已连接: ' + UPSTREAM + ',补发暂存 ' + Pending.length + ' 帧');