如何检测住宅代理
1 分•作者: jwally•13 天前
我现在感觉非常沮丧,希望分享我一月份发现的这个小异常能帮助大家让世界变得更美好,并找到打击网络犯罪的方法。去他妈的罪犯。
我所见过的绝大多数住宅代理提供商都不支持 UDP。UDP 是 WebRTC 使用的协议,自 2021 年以来一直是浏览器“核心”的一部分。如果有人说他们使用的是 Chrom(<i>)、FireFox、Safari,那么他们就拥有这个功能。
所以设置如下:
1. 创建一个子域名来获取客户端的 TCP IP 地址。通过不为其提供 AAAA 记录,可以强制其使用 IPv4。这将使未来的比较更容易。
2. 创建一个子域名来获取客户端的 UDP IP 地址。同样,也处理一下 AAAA 记录。你需要运行自己的 STUN 服务器(是你吗,Claude?是我,Justin……)。为了使其难以篡改,我让 STUN 服务器加密 IPv4 地址和其他一些信息,并将其作为 IPv6 ICE 候选者返回。这有点滥用,但有效,而且我不用担心后端服务器通信成为瓶颈。只需捕获、加密、返回即可。
算法如下:
*** 你拥有 TCP 和 UDP IP 地址 ***
1. 如果两个 IP 地址相同——可能不是住宅代理。
2. 如果两个 IP 地址不同,但属于同一个 ASN 且在同一个…/24(?) 网段内——它们属于蜂窝网络。
3. 如果 IP 地址属于不同的 ASN——这是一个重大危险信号。大多数使用住宅代理的人都被告诫过——关闭 WebRTC。这在 2010 年代中期曾出现过严重泄露,人们至今仍对此感到恐惧。
4. 如果其中一个地址属于 Cisco Web Umbrella 或 zScaler,而另一个是住宅地址——它们位于企业保护防火墙之后。这本身不算代理,但会触发此算法。根据你的威胁模型,它们可能可以被列入白名单。
*** 你 __只有__ TCP IP ***
这就是让这个方法奏效的“一个奇怪的技巧”/秘诀/什么的。TLS 持续时间/TCP RTT > 3.0
* “许多住宅代理在出口处分割连接:源的 TCP 套接字在那里结束,因此 Linux TCP_INFO 仅估计源 <=> 出口 RTT。出口将 TLS 握手字节转发给真正的客户端,使得客户端 Hello 握手完成包含隐藏的代理链。异常高的 TLS 持续时间/TCP RTT 比会暴露这种分割。” *
这基本上就是我们所需要的。从这里开始,我们只需执行以下操作:
TCP == UDP === 不是代理
TCP ~= UDP === 如果在同一个 ASN 内,不是代理
TCP != UDP === 代理或 zScaler 情况。根据需要列入白名单。
没有 UDP 且 TLS/TCP RTT 比率 < 3 === 可能不是代理(这里的数值越低越好)
没有 UDP 且 TLS/TCP RTT > 3 === 可能是代理(我见过的大多数都在 6-12 倍之间浮动)
在过去的 6 个月里,我一直在研究这个方法,主要与 Soax、BrightData 和 OxyLabs 代理合作。我还构建了自己的 ProxyDevice(Android)和 C2——将其放在我自己的网络上,它就捕捉到了。
这非常酷,因为这意味着你不需要将 IP 地址列入黑名单(即使列了也没用),因为合法用户和代理会来自同一个 IP——代理客户端看起来会 _非常_ 不同。它们会被 NetAcuity/MaxMind/StaticList 阻止——整个 IP 都被禁用。这是精准打击。
这可能并不完美,但根据我有限的经验,它准确得令人毛骨悚然。我不敢声称它在所有情况下都 100% 准确,但如果它比什么都没有好——那么根据定义,它就比什么都没有好——这就有帮助。归根结底,我只想通过这个来提供帮助。
附注:我很乐意分享我构建的东西。测试、证据、代码,随便什么。告诉我一声就行。
查看原文
I'm feeling pretty depressed right now, and hopefully sharing this little anomaly I discovered in January might help someone make the world a better place, and figure out how to put a dent in online crime. Fuck criminals.<p>Most residential proxy providers that I've seen don't support UDP. UDP is what WebRTC uses and has been part of the browser's "core" since 2021. If someone says they're on Chrom(<i>), FireFox, Safari - they have it.<p>So the setup goes like this:<p>1) Create a subdomain to get the client's TCP ip address. You can force it to ipv4 by not giving it an AAAA record. This will make future-comparison easier.<p>2) Create a subdomain to get the client's UDP ip address. Ditto the quad-a bit. You'll want to run your own STUN server (are you there, Claude? Its me, Justin...). To make it tamper resistant, I have the STUN server encrypt the ipv4 address and some other stuff and return it as an ipv6 ice candidate. Its abuse, but it works and I don't have to worry about back-end-server communication bottle necking anything. Just catch, encrypt, return.<p>And the algorithm looks like this:<p>**</i> YOU HAVE A TCP AND UDP IP ADDRESS ***<p>1) If both IP Addresses are the same - probably not a residential proxy<p>2) If both IP Addresses are different but on the same ASN and in the same .../24(?) - they're on a cell network<p>3) If the IP Addresses are on different ASNs - that's a MAJOR red flag. Most people who use residential proxies have it drilled into their head - TURN OFF WebRTC. This leaked bad in the mid 2010's and people are still terrified of it.<p>4) If one of the Addresses is on Cisco Web Umbrella or zScaler - and other is residential - they're behind a corporate protection firewall. Not really a proxy per se, but it'll trip this algorithm. Based on your threat model, they're probably ok to whitelist.<p>*** YOU __ONLY__ HAVE TCP IP ***<p>So this is the "one weird trick" / secret sauce / whatever that makes this work. TLS-duration / TCP-rtt > 3.0<p>* "Many residential proxies split the connection at the exit: the origin’s TCP socket ends there, so Linux TCP_INFO estimates only origin <=> exit RTT. The exit forwards TLS handshake bytes to the true client, making ClientHello handshake-complete include the hidden proxy chain. An unusually high TLS-duration/TCP-RTT ratio exposes that split." *<p>This is really all we need. From here, we just do the following:<p>TCP == UDP === not proxy<p>TCP ~= UDP === if on same ASN, not proxy<p>TCP != UDP === proxy or zScaler-thing. Whitelist to suit.<p>No UDP and TLS/TCP RTT Ratio < 3 === probably not a proxy (lower is better here)<p>No UDP and TLS/TCP RTT > 3 === probably a proxy (most I've seen float between 6-12x)<p>I've worked with this thing for the last 6 months and have worked mainly with Soax, BrightData, and OxyLabs proxies. I also built my own ProxyDevice (android) and C2 - put it on my own network and it caught it.<p>This is extremely cool because this means you don't have to blacklist IP addresses (not like it works) since a legitimate user and a proxy will come from the same IP - the proxy client will look _very_ different. They get blocked by NetAcuity/MaxMind/StaticList - the entire IP is killed. This is surgical.<p>This probably isn't perfect, but based on my limited experience its spooky accurate. I won't claim its 100% accurate for all cases everywhere but if its better than nothing - by definition its better than nothing - and that helps. Which, at the end of the day is all I want to do with this - help.<p>p.s. more than happy to share what I've built. Test, evidence, code, whatever. Just let me know.