JavaScript实现端口敲击在Linux正常,Windows下异常求助
解决Windows 7 Chrome中Fetch端口敲击的重复请求与顺序混乱问题
看起来你遇到的核心问题是旧版Chrome(Windows 7上的最终支持版本是Chrome 109)在连接失败时会自动重试TCP连接,而且这种重试行为会打乱你严格需要的端口敲击顺序,同时产生多余的连接请求。Ubuntu上的新版Chrome已经调整了这类重试策略,所以表现正常。
下面给你两个可行的解决方案,都能确保只发送单次SYN包,并且严格保持敲击顺序:
方案一:用AbortController限制Fetch请求,避免浏览器重试
通过AbortController在请求发起后立刻中止,从根源上阻止浏览器因连接失败而触发的重试逻辑,同时添加固定延迟保证顺序:
(async function() { const targetPorts = [7000, 8000, 9000]; const targetHost = "https://xx.xx.xx.xx"; for (const port of targetPorts) { const abortController = new AbortController(); // 100ms后强制中止请求,只需要发送SYN包即可,不需要等待完整HTTP响应 const abortTimeout = setTimeout(() => abortController.abort(), 100); try { await fetch(`${targetHost}:${port}`, { signal: abortController.signal, mode: 'no-cors' // 关闭跨域检查,减少额外请求开销 }); } catch (err) { // 忽略中止错误,只关注连接失败的情况(说明SYN包已发出) if (err.name !== 'AbortError') { console.log("SYN packet sent on port:", port); } } finally { clearTimeout(abortTimeout); } // 给服务器预留处理时间,确保下一次敲击前上一个的信号已经被处理 await new Promise(resolve => setTimeout(resolve, 200)); } })();
为什么这样有效:
AbortController会在短时间内终止请求,浏览器来不及触发重试机制;no-cors模式避免了浏览器发送OPTIONS预请求,减少不必要的网络交互;- 循环中的
await和固定延迟确保了端口敲击的顺序严格按照数组执行,不会出现乱序。
方案二:改用WebSocket发送SYN包
WebSocket在握手阶段首先会发送TCP SYN包,旧版Chrome对WebSocket连接失败的重试行为远少于Fetch。我们可以利用这一点来实现端口敲击:
(async function() { const targetPorts = [7000, 8000, 9000]; const targetHost = "xx.xx.xx.xx"; for (const port of targetPorts) { await new Promise((resolve) => { const ws = new WebSocket(`wss://${targetHost}:${port}`); // 无论连接成功/失败/超时,都立刻清理并进入下一个端口 const cleanup = () => { ws.close(); resolve(); }; ws.onerror = () => { console.log("SYN packet sent on port:", port); cleanup(); }; ws.onopen = cleanup; ws.onclose = cleanup; // 100ms超时,防止连接挂起 setTimeout(cleanup, 100); }); await new Promise(resolve => setTimeout(resolve, 200)); } })();
为什么这样有效:
- WebSocket的连接流程只需要发送SYN包即可触发服务器的端口敲击检测,不需要完成完整的握手;
- 旧版Chrome对WebSocket连接失败的重试次数极少(甚至不重试),不会产生多余的请求;
- 同样通过
await和延迟保证了敲击顺序的严格性。
问题根源补充
Windows 7上的Chrome版本(≤109)对HTTP连接失败的重试逻辑和新版Chrome不同,当服务器拒绝连接时,浏览器会自动重试2-3次TCP连接,这就导致了服务器日志中出现多个重复的Stage记录。同时,重试的异步特性可能打乱原本的请求顺序,进而破坏端口敲击的时序要求。
内容的提问来源于stack exchange,提问作者Esteban Panelli
相关产品推荐
相关产品推荐

