diff --git a/server.js b/server.js index 5e919dd..c6cb717 100644 --- a/server.js +++ b/server.js @@ -160,11 +160,21 @@ function tcpCheck(host, port, timeoutMs = 6000) { // 1) Cloudflare的520/521/522/523/524是"源站不可达"专属状态码,能连上CDN但源站挂了会明确返回这几个码; // 2) 再做一次真正的WebSocket握手,直接对应Xray/sing-box监听WS的那一层,比单看状态码更准。 // 两个都过才算正常。 -function httpStatusCheck(host, wsPath, timeoutMs = 8000) { +// 注意:连接必须用line.addr(真实服务器/CDN边缘地址)+ line.port(真实端口,不能写死443, +// 很多自建线路会用非标准端口);但HTTP Host头和TLS SNI要用line.host/line.sni(伪装域名), +// 不能也用addr——如果源站是按Host头路由的(Nginx server_name/反代规则),Host发错了根本到不了 +// 正确的源站,会拿到无关响应甚至连接失败,跟真实客户端的连接行为对不上。 +function httpStatusCheck(line, timeoutMs = 8000) { return new Promise((resolve) => { + const routeName = line.host || line.sni || line.addr; const req = https.request({ - hostname: host, port: 443, path: wsPath || '/', method: 'GET', timeout: timeoutMs, - headers: { 'User-Agent': 'Mozilla/5.0' }, + hostname: line.addr, + port: Number(line.port) || 443, + path: line.ws_path || '/', + method: 'GET', + timeout: timeoutMs, + servername: line.sni || routeName, // TLS SNI + headers: { 'User-Agent': 'Mozilla/5.0', Host: routeName }, }, (res) => { res.resume(); const badGateway = [520, 521, 522, 523, 524].includes(res.statusCode); @@ -175,7 +185,7 @@ function httpStatusCheck(host, wsPath, timeoutMs = 8000) { req.end(); }); } -function wsHandshakeCheck(host, wsPath, timeoutMs = 8000) { +function wsHandshakeCheck(line, timeoutMs = 8000) { return new Promise((resolve) => { let done = false; let ws; @@ -186,7 +196,13 @@ function wsHandshakeCheck(host, wsPath, timeoutMs = 8000) { resolve(ok); }; try { - ws = new WebSocket(`wss://${host}${wsPath || '/'}`, { handshakeTimeout: timeoutMs }); + const port = Number(line.port) || 443; + const routeName = line.host || line.sni || line.addr; + ws = new WebSocket(`wss://${line.addr}:${port}${line.ws_path || '/'}`, { + handshakeTimeout: timeoutMs, + headers: { Host: routeName }, + servername: line.sni || routeName, // TLS SNI + }); ws.on('open', () => finish(true)); ws.on('unexpected-response', () => finish(false)); ws.on('error', () => finish(false)); @@ -200,8 +216,8 @@ function wsHandshakeCheck(host, wsPath, timeoutMs = 8000) { async function checkLineConnectivity(line) { if (line.protocol === 'vless-cdn') { const [httpOk, wsOk] = await Promise.all([ - httpStatusCheck(line.addr, line.ws_path), - wsHandshakeCheck(line.addr, line.ws_path), + httpStatusCheck(line), + wsHandshakeCheck(line), ]); return httpOk && wsOk; }