26

I'm looking for a method, or a way to detect clients using any type of proxy server viewing my web site. I'm using PHP/Apache... what's the best way to do this? Any proxy server would need to be detected, not specifically one or the other.

Edit

I am more interested in the anonymous proxies... as the normal ones are easily detected by looking for HTTP_X_FORWARDED_FOR.

Another Edit

Try this:

1) go to http://kproxy.com (or any other free anonymous proxy site)

2) visit: http://www.worldofwarcraft.com

3) they are able to block somehow, as the page errors out with "Error loading stylesheet: A network error occurred loading an XSLT stylesheet:http://kproxy.com/new-hp/layout/layout.xsl"

I want to do something similar to prevent proxies.

Adam Azad
  • 11,171
  • 5
  • 29
  • 70
Kladskull
  • 10,332
  • 20
  • 69
  • 111
  • Which intention do you have? Is it any cache-disabling or sth else? – guerda May 13 '09 at 14:51
  • worldofwarcraft.com loads fine through kproxy.com for me, it's just missing the stylesheets which is probably due to how they are referenced in the html rather than some proxy blocker. – cOle2 May 13 '09 at 15:05
  • We intend to block anonymous sites from allowing users to view our website. Somehow, as mentioned above, Blizzard is able to do this by using a style sheet trick. – Kladskull May 13 '09 at 15:06
  • strange, its not loading for me using firefox. – Kladskull May 13 '09 at 15:07
  • I would recommend using IPQualityScore (http://ipqualityscore.com), it's free for 5000 lookups per month and way better than a simple HTTP_X_FORWARDED_FOR check. – Bravo Delta Jul 16 '17 at 02:32

10 Answers10

26

Use the following 2 solutions in PHP.

Method 1: quick but does not work with anonymous proxies

$proxy_headers = array(
    'HTTP_VIA',
    'HTTP_X_FORWARDED_FOR',
    'HTTP_FORWARDED_FOR',
    'HTTP_X_FORWARDED',
    'HTTP_FORWARDED',
    'HTTP_CLIENT_IP',
    'HTTP_FORWARDED_FOR_IP',
    'VIA',
    'X_FORWARDED_FOR',
    'FORWARDED_FOR',
    'X_FORWARDED',
    'FORWARDED',
    'CLIENT_IP',
    'FORWARDED_FOR_IP',
    'HTTP_PROXY_CONNECTION'
    );
foreach($proxy_headers as $x){
    if (isset($_SERVER[$x])) die("You are using a proxy!");
}

Method 2: portscan back to the origin IP at the normal proxy ports used.

$ports = array(8080,80,81,1080,6588,8000,3128,553,554,4480);
foreach($ports as $port) {
     if (@fsockopen($_SERVER['REMOTE_ADDR'], $port, $errno, $errstr, 30)) {
          die("You are using a proxy!");
     }
 }
AStopher
  • 4,207
  • 11
  • 50
  • 75
X-Ray
  • 301
  • 3
  • 2
  • 10
    I discourage the use of the second method - It often returns false positives. We've had issues with this on our site when using 3rd party proxy detection script that used this method. – HellaMad Nov 06 '12 at 02:04
  • 4
    The second method, not only it will take a lot of time and cannot be implemented on highly-trafficked websites, but it will also bring up an anti virus alert to some of the visitors! – Silviu-Marian May 01 '13 at 00:33
  • HTTP_X_FORWARDED_FOR returns a false postive using my normal internet direct connection. – Sumedh Jan 17 '15 at 05:57
  • This does not work, and it gives positives in my normal browser, with normal internet connection. – Fery Kaszoni Sep 14 '19 at 13:02
  • Forget this header checking code. I tested thousands of proxies, and the only header I got is "REMOTE_ADDR", none of the proxies give you any of the listed headers. The code is useless. – Feng Jiang Jan 17 '22 at 04:18
20

You can't detect that unless they pass on special headers which explictly mention it like X-Forwarded-For or something.

As far as I know you have to use a blacklist. Users who use putty portforwarding, VPN or other more sophisticated methods are undetactable as they behave exactly like normal users.

TomHastjarjanto
  • 5,386
  • 1
  • 29
  • 41
  • Yes, is there a trick that could be done? Something not cache-able, or forward-able? – Kladskull May 13 '09 at 14:48
  • There is no such trick, you as serverside developer can't see whether I connect through a VPN (yes, this is a proxy) or through my real internet connection. The tricks you mention only block certain web based anonymous proxies, but not the good ones using a VPS with putty portforwarding etc. – TomHastjarjanto May 14 '09 at 10:28
9

Metasploit uses lots of different techniques to force client's system to make direct connection (vulnerabilities/misfeatures in Flash, Java, QuickTime, MS Office, custom DNS server).

Alternatively, if you can't get client's browser to launch metasploit, you could try to look for open proxies (port scanning) and known Tor exit nodes.

But please don't assume that proxies are evil and need to be blocked – there are plenty of legitimate proxies and some users have to use them.

If you have trouble with spam or other abusive traffic then just blocking of proxies won't help much. You should look for specific solutions that address core of the problem (spam filters, IDS) rather than assuming anonymous = guilty.

Kornel
  • 97,764
  • 37
  • 219
  • 309
4

There are various paid / free solutions. Most of them looks at the client IP trying to connect to determine if they're on a proxy or not.

Paid:
Maxmind - They focus on fraud detection and have a sub-category for proxy detection. Note that this is now considered as a "legacy" service.

Free:
W I T C H - Able to detect OpenVPN by looking at MSS values that are uniquely identifiable. The code is available on github.

GetIpIntel - Proxy / VPN detection using machine learning, queries via API.

There are a few more free options listed on security stack exchange.

S W
  • 312
  • 2
  • 5
  • You can search for "IP2Proxy" in Google. It is also paid solutions with daily updated proxy IP addresses. – Michael C. Aug 10 '15 at 05:07
  • I just did some testing with IP2Proxy, it's not very accurate. From my experience, blocked / maxmind work well for paid solutions, and getIPIntel is the best free solution. – S W Aug 10 '15 at 05:57
  • Another proxy & VPN detection service worth adding to this list is IPQualityScore (https://www.ipqualityscore.com/). They have generous free and paid plans and the proxy detection is very accurate without flagging IPs as false-positives. – Johnny Jul 01 '17 at 09:12
  • GetIpIntel have a very low rate limit and the prices are insane. My application got rate limited after 2 hours of use by clients. – user10398534 Aug 19 '20 at 09:05
1

Old topic, but I might have figured something out.

It is live on my site and I think it might work for most cases.

My problem was that banned user were coming back to my site and re-registering with a new email address using one of the many proxies that you can find. What I have done is a simple jQuery call on the registration/login form:

<form id="login_form" method="post" action="/#fake_login_url">
   stuff you need for the form
</form>
<script>
   $('#login_form').attr('action','real_login_form');
</script>
Fabrizio
  • 3,734
  • 2
  • 29
  • 32
  • I'm assuming this only detects proxies that strip JS from network traffic? – sousdev Apr 29 '14 at 19:01
  • 2
    most proxies replace the URL for the post, executing the JS would put it back to normal. Make sure that the `real_login_form` is somewhat not in plain text, I.E.: `var url = 'ht'+'tp:'+'//'+'site'+'.com'+'/url'` – Fabrizio Jul 18 '14 at 15:04
1

Everything that the client passes to the server can be self-configured. You cannot trust anything, except for an IP address. So you cannot check the header data, if it's a proxy or a normal client.
By the way: It's the intention of a proxy not to show being a proxy :)

For sure, you could take the requester's IP address and send a http request you would send to a proxy. If it reacts, it may be a proxy otherwise, it's a normal client. This method would be very expensive and not reliable. If the proxy your server requested was behind a firewall, you would get no answer and think that it is a normal client.

guerda
  • 23,388
  • 27
  • 97
  • 146
  • Take a quick look at the example I edited in under "Another Edit". Some how blizzard was able to do some trick too fool the proxy server. – Kladskull May 13 '09 at 15:00
1

I think that what's happening here is some client-side JavaScript is trying to load something, and that can "see" that the page is being viewed inside a frame. That might be a more fruitful avenue to explore- as other answers have indicated, proxies intentionally make it hard to determine just from the server alone.

araqnid
  • 127,052
  • 24
  • 157
  • 134
-1

Even if it's an old question, I've had to check for proxy and unfortunatly none of the answers give good result.

After searching, I've found a better method. In order to understand this way of doing, just create a small page with this code:

 <?php
 foreach ($_SERVER as $key => $val)
 {
     echo $key."<br>\n";  
 }
 ?>

Run it direclty from your server. You'll see all keys from the header your server is sending. Then run the same script through a Proxy. You'll see (depending on the Proxy) 3 possible results:

  1. the Proxy add news keys/values
  2. the Proxy don't send all the original keys/values so some are missing.
  3. the Proxy send exactly the same keys/values but not in same order
  4. the Proxy send exactly the same keys/values, in same order

The 4th case can happen but others are the most frequent. So you just have to create an array with the key/value from your server (based on the result when you run the script without a Proxy) and compare the keys/values from $_SERVER. If you don't have exacty the same keys/values (less, more or in other order) you can assume the page came from a Proxy.

Notice I agree with those saying in some cases Proxy can be use in a "legal".

Peter
  • 1,247
  • 19
  • 33
-2

i feel like answering an 8 year old thread is useless, but i will answer anyways for future reference.
I dont know about proxies, but most VPN's (if you go to them) will bring some sort of error page. if you did something like...

$cont = file_get_contents($_SERVER["REMOTE_ADDR"]); //the users ip
$errormsg = "nginx";
if(strpos($cont, $errormsg)){
    die("No VPN's or Proxies Allowed");
}

this is very basic, you could get an array of the error messages and do it that way.
This will not work if the user has portforwarded their 80 port, but i dont see why the common person would do this.

Mcclures
  • 1
  • 5
-5

I'm using the following, but I'm not sure if it is working every time. It's just an idea :)

<?php
$host = gethostbyaddr($_SERVER['REMOTE_ADDR']);
if ($host != $_SERVER['REMOTE_ADDR']) die('Proxy detected.');
?>
Tamás Pap
  • 17,777
  • 15
  • 70
  • 102
  • 6
    This will fail for many users, because gethostaddr returns most of the time the username and providername such as: 5ED042DD.dynamic..com – Codebeat Nov 26 '11 at 04:15