You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:32:01