代理检测

检测网站

延迟检测代理

一个用户在正常上网,他在浏览器里测出来的网络往返延迟(RTT),理应和他在服务器端 TCP 握手时测出的延迟非常接近。一旦这两者出现巨大偏差(浏览器端延迟远大于服务器端底层延迟),说明中间极大概率存在代理或隧道。

服务器端看到的延迟(TCP 握手 RTT)
服务器通过网卡监听直接与它建立连接的那个 IP(即代理服务器的 IP)。在 TCP 三次握手期间,服务器精确测量 SYN-ACK 到 ACK 的时间。这个延迟反应的是“代理服务器到目标网站服务器”之间的网络耗时。

浏览器端看到的延迟(WebSocket 延迟)
JavaScript 在浏览器内部发起测量(传统的 XMLHttpRequest 会受到浏览器内部队列、排队和 TTFB 机制的干扰,因此最终升级为使用 WebSocket 建立双向通信并发送时间戳)。这个延迟反应的是“用户本地浏览器 $\rightarrow$ 代理服务器 $\rightarrow$ 目标网站服务器”整条链路的往返耗时。

无代理的真实用户:浏览器直连服务器。浏览器测出的延迟 $\approx$ 服务器端 TCP 握手延迟(两者的误差通常在 10% 左右以内)。
使用代理/爬虫的用户:流量经过了中转。浏览器测出的延迟包含了“浏览器到代理”+“代理到服务器”的全长;而服务器端 TCP 握手只测到了“代理到服务器”的后半段。因此,WebSocket 延迟会显著高于 TCP 握手延迟(文章实测 Brightdata/ScrapingBee 等代理服务的差值普遍在 45% 到 136% 之间)。

通过“端到端(浏览器)延迟”与“底层传输(TCP 握手)延迟”的非对称性、时间差比对来抓包代理。

webRTC泄露检测代理

WebRTC 作为一个需要极低延迟的 P2P 实时音视频通信协议,具备绕过系统默认代理设置、直接向底层网卡查询真实 IP 的“特权”。

当你使用 WebRTC(比如在网页上打 Google Meet、Discord 语音)时,为了保证音视频尽量不卡顿,浏览器需要找到你和对方之间最短、最快的物理网络路径。

为了实现这一点,WebRTC 引入了一个叫做 ICE(Interactive Connectivity Establishment,交互式连接建立) 的框架。ICE 框架会疯狂收集你这台设备上所有可能的网络接口和 IP 地址(被称为 ICE Candidate / ICE 候选者),包括:

Host Candidate(主机候选者):你设备的内网 IP(如 192.168.1.100 或内网 IPv6)。

Server Reflexive Candidate(服务器反射候选者):通过 STUN 服务器探查到的公网出口 IP(即你的运营商分配给你的真实公网 IP)。

Relay Candidate(中继候选者):通过 TURN 服务器中转的 IP。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
              ┌────────────────────────────────────────────────────────┐
│ 目标服务器 │
└─┬────────────────────────────────────────────────────┬─┘
│ │
路线 ① : 物理 HTTP 请求 路线 ② : 应用层 WebRTC 上报
(经过代理, 带有代理 IP) (绕过代理, 查出真实 IP)
│ │
▼ ▼
[网卡/日志抓取到 Request] [JS 脚本发送 JSON 数据]
`REMOTE_ADDR = 代理 IP` `{ webrtc_ip: "真实 IP" }`
│ │
└───────────────────┬────────────────────────────────┘
│
▼
【服务器后端 (Backend) 比对】
判断: 代理 IP == 真实 IP ?
│
┌──────────────┴──────────────┐
▼ ▼
【不一致】 【一致】
判定为开启代理 判定为正常直连
  1. 动态创建无用的 PeerConnection
    网站的 JavaScript 脚本并不需要真正去建立一个视频通话,它只需要在后台静默创建一个 RTCPeerConnection 对象:
1
2
3
4
// 网站在网页后台运行这段 JS
const pc = new RTCPeerConnection({
iceServers: [{ urls: "stun:stun.l.google.com:19302" }] // 指向一个公共的 STUN 服务器
});
  1. 强制触发 ICE 候选者收集
    脚本创建一个虚拟的“连接邀请”(Offer),开启 ICE 候选者收集流程:
1
2
pc.createDataChannel(""); // 创建数据通道以激活 ICE
pc.createOffer().then(offer => pc.setLocalDescription(offer));
  1. 浏览器网络栈的“越狱”行为(关键点!)

普通 HTTP/HTTPS 流量:当你开启了浏览器代理(如 HTTP/SOCKS5 代理插件)时,浏览器的普通网页请求都会规规矩矩地交给代理服务器转发。

WebRTC 的 UDP 流量:为了追求极致速度,WebRTC 默认会直接调用操作系统的底层的原生网络 API,向 STUN 服务器发送 UDP 数据包。它不会经过浏览器的 HTTP/SOCKS5 代理!

结果:STUN 服务器收到来自你设备的 UDP 包后,看清了你的真实出口 IP,并把这个 IP 写入回复包中传回给你的浏览器。

  1. JavaScript 拦截并提取候选者信息
    网页脚本监听 onicecandidate 事件。当浏览器收集到本地和外网的候选者信息时,脚本直接把这个数据抓取出来:
1
2
3
4
5
6
pc.onicecandidate = (event) => {
if (event.candidate) {
console.log("检测到 Candidate 信息:", event.candidate.candidate);
// 候选者字符串中直接包含了真实的 IP 地址!
}
};

TCP MTU / MSS 与包碎片检测

原理:代理协议(如 VPN、IPsec、WireGuard、Shadowsocks)通常会在原始数据包外层再封装一层自定义协议头。

这会导致数据包的 MTU(最大传输单元) 变小(例如从标准的 1500 字节降到 1420 字节或更低),从而使 TCP 的 MSS(最大报文段长度) 发生异常变化。

如果某个连接的 MSS 呈现典型的 VPN 封装特征,风控系统就会标记该连接启用了 VPN/隧道加密。

  1. 客户端/路由层:TCP MSS 钳制(MSS Clamping)与修改

在 TCP 三次握手阶段,客户端发送的 SYN 包里会包含一个 MSS 选项(告知服务器“我能接收的最大 TCP 载荷”)。正常以太网:$\text{MTU} = 1500$,减去 IP 头(20)和 TCP 头(20),$\text{MSS} = 1460$。WireGuard/VPN 开启后:虚拟网卡 $\text{MTU} = 1420$,算出的 $\text{MSS} = 1380$。

在操作系统底层或路由节点(如 iptables / nftables),强行拦截并修改握手包里的 MSS 值,将其篡改/伪装成标准值(1460 或 1440):

1
2
# Linux 下通过 iptables 强行修改 TCP SYN 包中的 MSS 值
iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1460
  1. 协议层设计:避免层层封装导致的 MSS 缩减(如 WireGuard / QUIC)

老一代 VPN(如 IPsec、OpenVPN)会在 IP 层上面一层层嵌套(IP in IP / UDP in IP),导致头部越来越厚,MTU 被严重挤压。

现代对抗协议(如 TuIC, Hysteria2, Xray / VLESS)采用了完全不同的思路:

基于 UDP / QUIC 的多路复用:
现代代理不再为每个 TCP 连接都去建立一个单独的代理隧道,而是在客户端和代理服务器之间建立一条固定的 UDP/QUIC 管道。

对于外网风控服务器来说,它看到的是你和代理服务器之间的标准 QUIC 流量(类似访问普通的 HTTP/3 网站),握手时的 MSS/MTU 遵循标准的 UDP/QUIC 协商规则。

你的真实目标请求(比如访问 Google)被打包在 QUIC 的流(Stream)里,外网目标服务器根本看不到你客户端虚拟网卡的 MSS,它看到的只是代理服务器公网网卡发出的标准 TCP/MSS。

  1. 对抗“包碎片检测”:PMTUD 与 Clamp 协商

风控系统经常结合检测 DF (Don’t Fragment) 标志位 和 ICMP “Fragmentation Needed” 数据包。

当代理发起传输时:

启用 PMTUD(路径 MTU 发现):确保数据包在到达代理服务器之前,不超载、不触发分片。

利用 MSS 协商(Clamping Down):如果一定要防检测,可以在本地代理客户端把 MSS 统一规范化为几个最常见的公网标准值(如 1440 或 1450,这两个值在移动 4G/5G、PPPoE 宽带中极其普遍,不会引发风控怀疑),而不是暴露极其特殊的 1380 或 1360 这种明显的 VPN 特征值。

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2015-2026 SunZhiqi

此时无声胜有声!

支付宝
微信