返回博客
网络

UDP over SOCKS5:隧道转发 QUIC 和 STUN 流量防止 IP 泄露

UDP over SOCKS5 代理隧道完整指南。了解 QUIC 和 WebRTC STUN 流量如何泄露真实 IP,以及 BotBrowser 如何自动通过 SOCKS5 隧道传输 UDP 流量。

简介

大多数代理配置只关注 TCP 流量。HTTP、HTTPS 和标准网络请求都使用 TCP,所有代理协议都能很好地处理它们。但现代浏览器并不只使用 TCP。两个关键协议 QUIC(HTTP/3)和 WebRTC STUN 依赖 UDP。当你的代理只处理 TCP 时,这些 UDP 数据包会直接从你的机器发送到目标服务器,完全绕过代理隧道。结果是:当你的 TCP 流量被安全代理时,你的真实 IP 地址却通过 UDP 流量泄露了。

这不是理论上的风险。Chrome 默认对 Google 服务、YouTube 和任何支持 HTTP/3 的站点使用 QUIC。WebRTC STUN 请求使用 UDP 发现你的公网 IP 地址以建立点对点连接。如果这两种协议没有通过代理路由,它们都会主动暴露你的真实 IP。

BotBrowser 通过自动 UDP over SOCKS5 支持解决了这个问题。当你的 SOCKS5 代理支持 UDP ASSOCIATE 时,BotBrowser 会自动将 QUIC 和 STUN 流量通过隧道传输。当代理不支持时,BotBrowser 会优雅地回退到基于 TCP 的替代方案,无需更改配置。

隐私影响

未受保护的 UDP 流量对隐私的影响非常显著。考虑一下当你用 SOCKS5 代理配置标准浏览器时会发生什么:

QUIC/HTTP/3 流量会向目标服务器泄露你的 IP。 当 Chrome 连接到支持 HTTP/3 的站点时,它会尝试通过 UDP 建立 QUIC 连接。如果代理只处理 TCP,这个 QUIC 连接就会直连。目标服务器在 QUIC 数据包上看到你的真实 IP 地址,即使你的 HTTP/2 回退流量走的是代理。Google 服务、YouTube、Cloudflare 托管的站点以及许多其他主要平台都支持 QUIC。

WebRTC STUN 请求暴露你的公网 IP。 STUN(NAT 会话穿越工具)是一种基于 UDP 的协议,用于发现你的公网 IP 地址。当页面上的 JavaScript 创建 RTCPeerConnection 时,浏览器会向 STUN 服务器发送 STUN 绑定请求。这些 UDP 数据包不走 TCP 代理路径,STUN 服务器会返回你的真实公网 IP。任何站点都可以在无需用户许可的情况下通过 WebRTC API 收集这些信息。

不一致性本身就是一个信号。 如果追踪系统观察到你的 HTTP 流量来自一个 IP(代理),但你的 QUIC 或 STUN 流量显示另一个 IP(你的真实 IP),这种不匹配是使用代理的明确指示。这种不一致性对隐私的损害可能比完全不使用代理更大。

UDP 流量路径:直连 vs. 隧道 仅 TCP 代理(UDP 泄露): 浏览器 SOCKS5 代理 Web 服务器 STUN / QUIC 服务器 TCP TCP UDP 直连 - 真实 IP 暴露! UDP over SOCKS5(所有流量隧道传输): BotBrowser UDP ASSOCIATE SOCKS5 代理 UDP 支持 Web 服务器 STUN / QUIC 服务器 TCP TCP UDP 隧道 UDP 经代理 使用 UDP over SOCKS5:QUIC 和 STUN 流量通过代理隧道传输。 目标服务器在 TCP 和 UDP 连接上都只能看到代理 IP。 TCP(代理) UDP(泄露) UDP(隧道)

技术背景

QUIC(HTTP/3):基于 UDP 的 Web 协议

QUIC 是 HTTP/3 背后的传输协议。与运行在 TCP 上的 HTTP/2 不同,QUIC 使用 UDP 来减少连接延迟并提升性能。当服务器支持 QUIC 时,Chrome 默认使用它。包括 Google 搜索、YouTube、Gmail、Google Cloud 和所有 Cloudflare 托管的站点在内的主要平台都支持 QUIC。

当浏览器发送 QUIC 数据包时,它是一个 UDP 数据报。只处理 TCP 连接的标准代理配置不会拦截这些流量。QUIC 数据包直接从你的机器发送到目标服务器,源地址中携带了你的真实 IP。

STUN(WebRTC):基于 UDP 的 IP 发现

STUN 是一种帮助 NAT 后面的设备发现其公网 IP 地址的协议。浏览器在 WebRTC 的 ICE(交互式连接建立)过程中使用 STUN。当 JavaScript 创建 RTCPeerConnection 时,浏览器向 STUN 服务器发送 STUN 绑定请求(UDP)。服务器响应它看到的公网 IP 地址。

这是 WebRTC 的设计特性,不是 bug。但从隐私角度来看,这意味着任何网页都可以通过发起 STUN 请求来发现你的真实公网 IP,即使你所有的 HTTP 流量都通过代理路由。

UDP ASSOCIATE:SOCKS5 的 UDP 转发

SOCKS5 协议(RFC 1928)定义了三种命令类型:

  1. CONNECT(0x01):通过代理建立 TCP 连接。这是大多数工具使用的方式。
  2. BIND(0x02):在代理上设置 TCP 监听器以接受传入连接。
  3. UDP ASSOCIATE(0x03):通过代理建立 UDP 中继。

UDP ASSOCIATE 是隧道传输 UDP 流量的关键。它的工作方式如下:

  1. 客户端通过 TCP 向 SOCKS5 代理发送 UDP ASSOCIATE 请求
  2. 代理分配一个 UDP 中继端点并返回其地址
  3. 客户端将 UDP 数据包发送到此中继端点,用 SOCKS5 UDP 头部封装
  4. 代理解封头部并将 UDP 数据包转发到预期目标
  5. 来自目标的响应通过代理中继返回

目标服务器看到的 UDP 数据包来自代理的 IP,而不是你的机器。QUIC 和 STUN 流量都可以使用此机制。

完整流程

当 UDP over SOCKS5 正常工作时,完整流程如下:

  1. 协商:BotBrowser 建立到 SOCKS5 代理的 TCP 连接并进行身份验证
  2. UDP ASSOCIATE 请求:BotBrowser 发送 UDP ASSOCIATE 命令以请求 UDP 中继
  3. 中继分配:代理创建 UDP 中继并返回中继地址
  4. 隧道传输:所有 UDP 流量(QUIC、STUN)通过中继发送,使用 SOCKS5 封装
  5. ICE 候选:WebRTC STUN 响应返回代理的 IP,因此 ICE 候选反映代理身份

BotBrowser 的方案

自动 UDP ASSOCIATE 检测

BotBrowser 自动检测你的 SOCKS5 代理是否支持 UDP ASSOCIATE。不需要额外的标志或配置。当你使用 --proxy-server 指定 SOCKS5 代理时,BotBrowser:

  1. 建立到代理的 TCP 控制连接
  2. 发送 UDP ASSOCIATE 请求以探测 UDP 支持
  3. 如果代理接受,BotBrowser 创建 UDP 中继隧道
  4. 如果代理拒绝(或不支持 UDP ASSOCIATE),BotBrowser 回退到 TCP 替代方案

此检测在代理初始化期间透明进行。

QUIC 流量通过隧道

当 UDP ASSOCIATE 可用时,QUIC 流量自动通过 SOCKS5 UDP 隧道路由。Chrome 的 QUIC 实现将隧道视为其网络路径,因此到 Google、YouTube、Cloudflare 和其他 HTTP/3 服务器的 QUIC 连接都使用代理 IP。

这意味着你可以获得 QUIC 的性能优势(更低延迟、更好的连接迁移、减少队头阻塞),同时保持一致的 IP 身份。

WebRTC STUN 通过隧道

STUN 绑定请求也通过 UDP 隧道路由。当页面发起 WebRTC 并且浏览器发送 STUN 请求时,这些 UDP 数据包通过 SOCKS5 中继。STUN 服务器看到的是代理的 IP 地址,并将其作为服务器反射候选返回。WebRTC 生成的 ICE 候选反映的是代理 IP,而不是你的真实 IP。

这提供了与 --bot-webrtc-ice 相同的保护,但通过不同的机制:不是在引擎层面控制 ICE 候选生成,而是 STUN 请求本身就通过代理传输。

不支持 UDP 时的优雅回退

不是所有 SOCKS5 代理都支持 UDP ASSOCIATE。许多住宅代理提供商和一些商业代理只处理 TCP CONNECT。当 BotBrowser 检测到 UDP ASSOCIATE 不可用时,它会优雅地回退:

QUIC 回退到 TCP 上的 HTTP/2。 Chrome 本身就内置了这个回退机制。当 QUIC 不可用(或 UDP 被阻止时),Chrome 使用 TCP 代理连接上的 HTTP/2。没有功能损失。页面加载相同的内容,只是使用 TCP 传输。

STUN 可以用 --bot-webrtc-ice 控制。 如果 UDP STUN 请求无法通过代理路由,使用 --bot-webrtc-ice 标志在引擎层面控制 ICE 候选生成:

chrome --bot-profile="/path/to/profile.enc" \
       --proxy-server="socks5://user:pass@proxy:1080" \
       --bot-webrtc-ice="google"

这确保无论 UDP 支持情况如何,WebRTC ICE 候选都显示代理 IP。

配置和使用

基本 CLI 设置

最简单的配置只需要 --proxy-server 配合 SOCKS5 代理:

chrome --bot-profile="/path/to/profile.enc" \
       --proxy-server="socks5://user:pass@proxy:1080"

如果代理支持 UDP ASSOCIATE,QUIC 和 STUN 流量将自动通过隧道传输。不需要额外的标志。

完整隐私配置

为了全面的网络保护,结合 DNS 和 WebRTC 控制:

chrome --bot-profile="/path/to/profile.enc" \
       --proxy-server="socks5://user:pass@proxy:1080" \
       --bot-local-dns \
       --bot-webrtc-ice="google"

此配置覆盖所有网络泄露路径:TCP 流量通过代理,UDP 流量通过 UDP ASSOCIATE(或回退),DNS 通过本地解析,WebRTC 通过控制的 ICE 候选。

Playwright 集成

const { chromium } = require('playwright-core');

(async () => {
  const browser = await chromium.launch({
    executablePath: '/path/to/botbrowser/chrome',
    args: [
      '--bot-profile=/path/to/profile.enc',
      '--proxy-server=socks5://user:pass@proxy:1080',
      '--bot-local-dns',
      '--bot-webrtc-ice=google',
    ],
    headless: true,
  });

  const context = await browser.newContext();
  const page = await context.newPage();
  await page.goto('https://www.youtube.com');

  // YouTube 的 QUIC 流量通过 UDP 隧道
  // STUN 请求通过 UDP 隧道
  // 所有流量使用代理 IP

  await browser.close();
})();

Puppeteer 集成

const puppeteer = require('puppeteer-core');

(async () => {
  const browser = await puppeteer.launch({
    executablePath: '/path/to/botbrowser/chrome',
    args: [
      '--bot-profile=/path/to/profile.enc',
      '--proxy-server=socks5://user:pass@proxy:1080',
      '--bot-local-dns',
      '--bot-webrtc-ice=google',
    ],
    headless: true,
    defaultViewport: null,
  });

  const page = await browser.newPage();
  await page.goto('https://www.youtube.com');
  await browser.close();
})();

Playwright 的 Per-Context 代理

管理多身份时,每个浏览器上下文可以使用不同的 SOCKS5 代理,具有独立的 UDP 隧道:

const { chromium } = require('playwright-core');

(async () => {
  const browser = await chromium.launch({
    executablePath: '/path/to/botbrowser/chrome',
    args: [
      '--bot-profile=/path/to/profile.enc',
    ],
    headless: true,
  });

  // 上下文 1:支持 UDP 的美国代理
  const context1 = await browser.newContext({
    proxy: {
      server: 'socks5://user1:pass1@us-proxy:1080',
    },
  });

  // 上下文 2:支持 UDP 的德国代理
  const context2 = await browser.newContext({
    proxy: {
      server: 'socks5://user2:pass2@de-proxy:1080',
    },
  });

  const page1 = await context1.newPage();
  const page2 = await context2.newPage();

  await page1.goto('https://example.com');
  await page2.goto('https://example.com');

  await browser.close();
})();

验证 UDP 隧道

要确认 UDP 流量通过代理隧道路由,检查 QUIC 和 WebRTC 行为:

const page = await context.newPage();

// 1. 验证 HTTP IP 匹配代理
await page.goto('https://httpbin.org/ip');
const httpIp = await page.textContent('body');
console.log('HTTP IP:', httpIp);

// 2. 检查 WebRTC ICE 候选中的代理 IP
const candidates = await page.evaluate(() => {
  return new Promise((resolve) => {
    const ips = [];
    const pc = new RTCPeerConnection({
      iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
    });
    pc.createDataChannel('test');
    pc.onicecandidate = (e) => {
      if (e.candidate) {
        const match = e.candidate.candidate.match(
          /([0-9]{1,3}\.){3}[0-9]{1,3}/
        );
        if (match) ips.push(match[0]);
      } else {
        resolve(ips);
      }
    };
    pc.createOffer().then(o => pc.setLocalDescription(o));
  });
});
console.log('ICE 候选 IP:', candidates);

// 两者都应显示代理 IP,而不是你的真实 IP

常见场景

场景 1:支持 UDP 的 SOCKS5 代理

这是理想配置。你的 SOCKS5 代理支持 UDP ASSOCIATE,BotBrowser 自动隧道传输所有流量。

流量类型路径结果
HTTP/HTTPS (TCP)浏览器 -> 代理 -> 目标代理 IP 可见
QUIC/HTTP/3 (UDP)浏览器 -> 代理 UDP 中继 -> 目标代理 IP 可见
STUN (UDP)浏览器 -> 代理 UDP 中继 -> STUN 服务器返回代理 IP
DNS由 --bot-local-dns 控制无泄露

配置:

chrome --bot-profile="/path/to/profile.enc" \
       --proxy-server="socks5://user:pass@proxy:1080" \
       --bot-local-dns

场景 2:不支持 UDP 的 SOCKS5 代理

许多 SOCKS5 代理,尤其是住宅代理,只支持 TCP CONNECT。BotBrowser 检测到这种情况后会自动回退。

流量类型路径结果
HTTP/HTTPS (TCP)浏览器 -> 代理 -> 目标代理 IP 可见
QUIC/HTTP/3回退到 TCP 上的 HTTP/2代理 IP 可见
STUN (UDP)由 --bot-webrtc-ice 控制候选中显示代理 IP
DNS由 --bot-local-dns 控制无泄露

配置:

chrome --bot-profile="/path/to/profile.enc" \
       --proxy-server="socks5://user:pass@proxy:1080" \
       --bot-webrtc-ice="google" \
       --bot-local-dns

--bot-webrtc-ice 标志即使没有 UDP 隧道也能确保 WebRTC 保护。

场景 3:HTTP/HTTPS 代理(不支持 UDP)

HTTP 和 HTTPS 代理使用 CONNECT 方法进行 TCP 隧道。它们完全不支持 UDP。BotBrowser 的处理方式与不支持 UDP 的 SOCKS5 代理相同。

流量类型路径结果
HTTP/HTTPS (TCP)浏览器 -> 代理 (CONNECT) -> 目标代理 IP 可见
QUIC/HTTP/3回退到 TCP 上的 HTTP/2代理 IP 可见
STUN (UDP)由 --bot-webrtc-ice 控制候选中显示代理 IP
DNS由 --bot-local-dns 控制无泄露

配置:

chrome --bot-profile="/path/to/profile.enc" \
       --proxy-server="http://user:pass@proxy:8080" \
       --bot-webrtc-ice="google" \
       --bot-local-dns

最佳实践

  1. 尽可能使用支持 UDP 的 SOCKS5 代理。 这以最少的配置提供最完整的保护。QUIC 和 STUN 流量自动隧道传输。

  2. 始终添加 --bot-webrtc-ice 作为安全网。 即使使用 UDP 隧道,--bot-webrtc-ice 标志也提供额外的 WebRTC 保护层,以防 UDP 隧道断开。

  3. 结合 --bot-local-dns 实现完整覆盖。 UDP 隧道、WebRTC 控制和 DNS 泄露防护一起关闭所有主要网络泄露路径。

  4. 测试你的代理的 UDP 支持。 并非所有代理都清楚地宣传其 UDP ASSOCIATE 功能。使用上述验证步骤确认 UDP 流量确实通过隧道路由。

  5. 不要手动禁用 QUIC。 一些指南建议使用 --disable-quic 禁用 QUIC。在 BotBrowser 中这是不必要的。当 UDP ASSOCIATE 可用时,QUIC 通过隧道工作。不可用时,QUIC 自动回退到 HTTP/2。完全禁用 QUIC 可能会创建可检测的指纹。

  6. 查看代理提供商文档。 询问你的代理提供商是否支持 SOCKS5 UDP ASSOCIATE。支持它的提供商包括大多数数据中心 SOCKS5 代理和一些高端住宅代理。

常见问题

UDP over SOCKS5 需要特殊的 BotBrowser 标志吗? 不需要。当你使用 --proxy-server 配合 SOCKS5 代理时,BotBrowser 会自动检测 UDP ASSOCIATE 支持。UDP 隧道本身不需要额外标志。

如果我的代理不支持 UDP ASSOCIATE 会怎样? BotBrowser 会优雅地回退。QUIC 流量降级到 TCP 上的 HTTP/2(仍通过代理)。对于 WebRTC 保护,添加 --bot-webrtc-ice 在引擎层面控制 ICE 候选。

这对 SOCKS5H 代理有效吗? 有效。socks5h:// 方案告诉 BotBrowser 通过代理解析 DNS。UDP ASSOCIATE 在 socks5://socks5h:// 方案下的工作方式相同。

可以在 Playwright 的 per-context 代理中使用 UDP over SOCKS5 吗? 可以。每个浏览器上下文可以有自己的 SOCKS5 代理,BotBrowser 将独立探测每个代理连接的 UDP ASSOCIATE 支持。

UDP 隧道会影响性能吗? 开销很小。SOCKS5 UDP 封装为每个 UDP 数据包添加一个小头部。对于 QUIC 流量,与 HTTP/2 回退相比,你仍然可以获得 HTTP/3 的延迟优势。中继添加一个网络跳转,类似于 TCP 代理。

UDP ASSOCIATE 和完整的 UDP 代理支持一样吗? UDP ASSOCIATE 是 RFC 1928 中定义的用于中继 UDP 流量的特定 SOCKS5 机制。它是通过 SOCKS5 隧道传输 UDP 的标准方式。一些代理提供商可能用不同方式描述其 UDP 支持,但在协议层面,它就是 UDP ASSOCIATE。

HTTP/HTTPS 代理支持 UDP 吗? 不支持。HTTP 和 HTTPS 代理使用 HTTP CONNECT 方法,只支持 TCP。如果你需要 UDP 隧道,必须使用 SOCKS5 代理。

如何判断我的 QUIC 流量是否通过隧道传输? 在 BotBrowser 中导航到 chrome://net-internals/#quic。如果 QUIC 会话处于活跃状态且你的代理支持 UDP,则流量正在正确隧道传输。你也可以检查 chrome://flags/#enable-quic 确认 QUIC 已启用。

总结

UDP 流量是基于代理的隐私设置中一个重要且经常被忽视的缺口。QUIC 和 WebRTC STUN 都使用 UDP,当你的代理只处理 TCP 时,两者都可能暴露你的真实 IP。BotBrowser 通过自动检测 SOCKS5 UDP ASSOCIATE 支持并将所有 UDP 流量通过代理隧道传输来关闭这个缺口。当 UDP 支持不可用时,BotBrowser 会回退到 TCP 替代方案,无需任何手动配置。

为了完整的网络隐私,将 UDP over SOCKS5 与代理配置WebRTC 泄露防护DNS 泄露防护结合使用。

#udp#socks5#quic#webrtc#stun#proxy#privacy#network