Settings

Theme

How to Detect Residential Proxies

4 points by jwally · 4 comments · 4 min read


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.

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(), FireFox, Safari - they have it.

So the setup goes like this:

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.

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.

And the algorithm looks like this:

** YOU HAVE A TCP AND UDP IP ADDRESS ***

1) If both IP Addresses are the same - probably not a residential proxy

2) If both IP Addresses are different but on the same ASN and in the same .../24(?) - they're on a cell network

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.

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.

*** YOU __ONLY__ HAVE TCP IP ***

So this is the "one weird trick" / secret sauce / whatever that makes this work. TLS-duration / TCP-rtt > 3.0

* "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." *

This is really all we need. From here, we just do the following:

TCP == UDP === not proxy

TCP ~= UDP === if on same ASN, not proxy

TCP != UDP === proxy or zScaler-thing. Whitelist to suit.

No UDP and TLS/TCP RTT Ratio < 3 === probably not a proxy (lower is better here)

No UDP and TLS/TCP RTT > 3 === probably a proxy (most I've seen float between 6-12x)

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.

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.

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.s. more than happy to share what I've built. Test, evidence, code, whatever. Just let me know.

1 thread
juros

This works in theory, and shows you've made good research on the topic. I operate an IP anonymizer detection service and these are the gotchas I think you'd find in real life though:

- some browsers / extensions disable webRTC by default, and certain privacy configs use a proxy to reach out to STUN. These are not "weird" browsers: Safari, Firefox, Brave, Opera do it by default or through configs.

- naive RTT calculations will cause you lots of false positives. Just as an example, some devices on low battery do slow down their network stack, randomly causing bigger RTT on some network packets and triggering your TLS > RTT*3. We discovered it the hard way, and there are many more other corner cases.

- as an independent site operator, I'd find this harder to deploy than i.e. deploying a reverse proxy or using 3rd party service. Also you'd need to always show an interstitial screen where the webRTC checks happen, instead of running your detections on the fly as each request comes in.

If you're interested on the topic, let's chat by email and/or take a look at our demos:

- https://demo.truesign.ai/protected-form

- https://demo.truesign.ai/protected-content

  • jwallyOP

    Super cool! Thanks for replying / sharing.

    Obviously, this would be a SAAS -I wouldn't want webmaster at jocokfuel.com or whatever having to roll their own rust stun server and make TCP RTT measurements :-)

    Spun up a quick and dirty demo at https://proxy.kyc.red

    More detailed description is in there.

    I just ran some proxied sessions through your demo - really impressive! FWIW, make the "BLOCKED" text bright red and bold - success/accepted green.

    Would love to chat more about what you're doing and how you're doing it.

    I'm justin at wolcott dot io

    :salute

Keyboard Shortcuts

j
Next item
k
Previous item
o / Enter
Open selected item
?
Show this help
Esc
Close modal / clear selection