3

I'm looking for the absolute best way of blocking proxies coming onto my site. The reason is due to me using unique IP address's on my project.

What would you recommend?

Thanks!

  • 4
    When you say that you're "using unique IP addresses" do you mean that you're assuming that each IP address represents a unique user? If that's the case then *stop making that assumption*, there's absolutely no way for you to ensure that each user has a unique IP. – LukeH Feb 18 '11 at 00:38
  • 1
    Using cookies is the real true way to give each user (each browser on a machine) an unique ID – Dan Feb 18 '11 at 00:58

7 Answers7

3

It is impossible to completely accurately determine whether the person connecting to your site is proxying that request for someone else.

The best you can reasonably do in realtime is look for an X-FORWARDED-FOR HTTP header, which some proxies will use to inform you the IP address of the client the proxy is connecting on behalf of.

$headers = apache_request_headers();
$forwarded = $headers['X-Forwarded-For'];

If you are assuming that each IP address corresponds to a different person, you are making a mistaken assumption. There are many more devices connected to the internet than available IPs. Everyone in a school typically shares an IP. Everyone in a large company typically shares an IP. Every AOL dialup user shares a couple IPs. Every MSN dialup user shares a couple IPs.

Dan Grossman
  • 51,866
  • 10
  • 112
  • 101
  • Hi Dan, Thanks for your comment. I was not expecting a perfect solution to be honest, I know that's out of reach. But anything that helps would be great. Could you please give me an example code for detecting the header? Thanks again. –  Feb 18 '11 at 00:36
  • +1 yep, and [Wikipedia](http://en.wikipedia.org/wiki/X-Forwarded-For) has some good info on it. – alex Feb 18 '11 at 00:36
  • Yes, many people share the same IP, but the chances of them all hitting your site at the same time is practically nil. If you have a good business reason for blocking proxies by IP, I'd do it – Henley Apr 05 '11 at 00:13
2

You should not be relying on unique IP addresses. Many people are behind a firewall at work or school, so one ip does not mean 1 machine or user.

If you want to identify your users, set a cookie, or use a session.

Byron Whitlock
  • 52,691
  • 28
  • 123
  • 168
  • Thanks Byron, I use sessions for my users but this is for tracking locations. –  Feb 18 '11 at 00:39
2

There are several types of proxies on the internet and a few pieces of code will not detect all of them. VPNs, web proxies, Tor, and open proxies are some examples of proxies that cannot always be detected with regular tools. The best way to handle and detect these various proxies is to use an updated blacklist of these proxy addresses. One example is BlockScript.

Joshua
  • 21
  • 1
1

I'm not aware of a bulletproof way to do this, but this would be pretty much complete:

if (get_ip_address() !== get_ip_address(true))
{
    echo 'using proxy';
}

This get_ip_address() function was adapted from this answer and goes as follows:

function get_ip_address($proxy = false)
{
    if ($proxy === true)
    {
        foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED') as $key)
        {
            if (array_key_exists($key, $_SERVER) === true)
            {
                foreach (array_map('trim', explode(',', $_SERVER[$key])) as $ip)
                {
                    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false)
                    {
                        return $ip;
                    }
                }
            }
        }
    }

    return $_SERVER['REMOTE_ADDR'];
}
Community
  • 1
  • 1
Alix Axel
  • 151,645
  • 95
  • 393
  • 500
  • I'm getting an error (Parse error: syntax error, unexpected T_AS) –  Feb 20 '11 at 13:25
  • @Alexwhin: I missed one parentheses, fixed now. – Alix Axel Feb 20 '11 at 13:28
  • Didn't seem to do anything, using a proxy showed nothing aswell as regular browsing :/ –  Feb 20 '11 at 14:09
  • @Alexwhin: It wasn't supposed to "show" anything, try again with the first snippet. – Alix Axel Feb 20 '11 at 14:14
  • @Alix I tried adding an echo, but it didn't seem to show anything :/ –  Feb 20 '11 at 19:53
  • @Alexwhin: Like I said, there is no bulletproof way. I bet you're using an anonymous proxy. – Alix Axel Feb 20 '11 at 19:55
  • Your help has been fantastic so far, but is their a better method prehaps? I understand that their is no complete way, so I don't expect it. I can always block certain domains (known proxies) but obviously I can't find and block everyone. –  Feb 20 '11 at 20:04
  • I'm afraid this is the most complete you're gonna get. =\ – Alix Axel Feb 20 '11 at 20:19
0

Add to .htaccess

RewriteEngine on
RewriteCond %{HTTP:VIA}                 !^$ [OR]
RewriteCond %{HTTP:FORWARDED}           !^$ [OR]
RewriteCond %{HTTP:USERAGENT_VIA}       !^$ [OR]
RewriteCond %{HTTP:X_FORWARDED_FOR}     !^$ [OR]
RewriteCond %{HTTP:PROXY_CONNECTION}    !^$ [OR]
RewriteCond %{HTTP:XPROXY_CONNECTION}   !^$ [OR]
RewriteCond %{HTTP:HTTP_PC_REMOTE_ADDR} !^$ [OR]
RewriteCond %{HTTP:HTTP_CLIENT_IP}      !^$
RewriteRule ^(.*)$ - [F]
0

The problem with this is, if you have a legitimate IP and include this header, and you make this header trump the IP, you will get incorrect results.

It may be worthwhile storing both separately.

alex
  • 479,566
  • 201
  • 878
  • 984
0

I've found a code taken from PhpMyAdmin which uses some possibilities of PHP to detect proxies and IPs behind proxies. For me this code worked many times, but not 100%. I paste it here for your tests and considerations

It returns FALSE when determining a strong proxy or user IP behind the transparent proxy

Check new versions of PhpMyAdmin for updates

function get_ip()
{
global $REMOTE_ADDR;
global $HTTP_X_FORWARDED_FOR, $HTTP_X_FORWARDED, $HTTP_FORWARDED_FOR, $HTTP_FORWARDED;
global $HTTP_VIA, $HTTP_X_COMING_FROM, $HTTP_COMING_FROM;
global $HTTP_SERVER_VARS, $HTTP_ENV_VARS;
// Get some server/environment variables values
if(empty($REMOTE_ADDR))
    {
    if(!empty($_SERVER)&&isset($_SERVER['REMOTE_ADDR']))
        {
        $REMOTE_ADDR = $_SERVER['REMOTE_ADDR'];
        }
    elseif(!empty($_ENV)&&isset($_ENV['REMOTE_ADDR']))
        {
        $REMOTE_ADDR = $_ENV['REMOTE_ADDR'];
        }
    elseif(!empty($HTTP_SERVER_VARS) && isset($HTTP_SERVER_VARS['REMOTE_ADDR']))
        {
        $REMOTE_ADDR = $HTTP_SERVER_VARS['REMOTE_ADDR'];
        }
    elseif(!empty($HTTP_ENV_VARS)&&isset($HTTP_ENV_VARS['REMOTE_ADDR']))
        {
        $REMOTE_ADDR = $HTTP_ENV_VARS['REMOTE_ADDR'];
        }
    elseif(@getenv('REMOTE_ADDR'))
        {
        $REMOTE_ADDR = getenv('REMOTE_ADDR');
        }
    } // end if
if(empty($HTTP_X_FORWARDED_FOR))
    {
    if(!empty($_SERVER) && isset($_SERVER['HTTP_X_FORWARDED_FOR']))
        {
        $HTTP_X_FORWARDED_FOR = $_SERVER['HTTP_X_FORWARDED_FOR'];
        }
    elseif(!empty($_ENV) && isset($_ENV['HTTP_X_FORWARDED_FOR']))
        {
        $HTTP_X_FORWARDED_FOR = $_ENV['HTTP_X_FORWARDED_FOR'];
        }
    elseif(!empty($HTTP_SERVER_VARS) && isset($HTTP_SERVER_VARS['HTTP_X_FORWARDED_FOR']))
        {
        $HTTP_X_FORWARDED_FOR = $HTTP_SERVER_VARS['HTTP_X_FORWARDED_FOR'];
        }
    elseif(!empty($HTTP_ENV_VARS) && isset($HTTP_ENV_VARS['HTTP_X_FORWARDED_FOR']))
        {
        $HTTP_X_FORWARDED_FOR = $HTTP_ENV_VARS['HTTP_X_FORWARDED_FOR'];
        }
    elseif(@getenv('HTTP_X_FORWARDED_FOR'))
        {
        $HTTP_X_FORWARDED_FOR = getenv('HTTP_X_FORWARDED_FOR');
        }
    } // end if
if(empty($HTTP_X_FORWARDED))
    {
    if(!empty($_SERVER) && isset($_SERVER['HTTP_X_FORWARDED']))
        {
        $HTTP_X_FORWARDED = $_SERVER['HTTP_X_FORWARDED'];
        }
    elseif(!empty($_ENV) && isset($_ENV['HTTP_X_FORWARDED']))
        {
        $HTTP_X_FORWARDED = $_ENV['HTTP_X_FORWARDED'];
        }
    elseif(!empty($HTTP_SERVER_VARS) && isset($HTTP_SERVER_VARS['HTTP_X_FORWARDED']))
        {
        $HTTP_X_FORWARDED = $HTTP_SERVER_VARS['HTTP_X_FORWARDED'];
        }
    elseif(!empty($HTTP_ENV_VARS) && isset($HTTP_ENV_VARS['HTTP_X_FORWARDED']))
        {
        $HTTP_X_FORWARDED = $HTTP_ENV_VARS['HTTP_X_FORWARDED'];
        }
    elseif(@getenv('HTTP_X_FORWARDED'))
        {
        $HTTP_X_FORWARDED = getenv('HTTP_X_FORWARDED');
        }
    } // end if
if(empty($HTTP_FORWARDED_FOR))
    {
    if(!empty($_SERVER) && isset($_SERVER['HTTP_FORWARDED_FOR']))
        {
        $HTTP_FORWARDED_FOR = $_SERVER['HTTP_FORWARDED_FOR'];
        }
    elseif(!empty($_ENV) && isset($_ENV['HTTP_FORWARDED_FOR']))
        {
        $HTTP_FORWARDED_FOR = $_ENV['HTTP_FORWARDED_FOR'];
        }
    elseif(!empty($HTTP_SERVER_VARS) && isset($HTTP_SERVER_VARS['HTTP_FORWARDED_FOR']))
        {
        $HTTP_FORWARDED_FOR = $HTTP_SERVER_VARS['HTTP_FORWARDED_FOR'];
        }
    elseif(!empty($HTTP_ENV_VARS) && isset($HTTP_ENV_VARS['HTTP_FORWARDED_FOR']))
        {
        $HTTP_FORWARDED_FOR = $HTTP_ENV_VARS['HTTP_FORWARDED_FOR'];
        }
    elseif(@getenv('HTTP_FORWARDED_FOR'))
        {
        $HTTP_FORWARDED_FOR = getenv('HTTP_FORWARDED_FOR');
        }
    } // end if
if(empty($HTTP_FORWARDED))
    {
    if(!empty($_SERVER) && isset($_SERVER['HTTP_FORWARDED']))
        {
        $HTTP_FORWARDED = $_SERVER['HTTP_FORWARDED'];
        }
    elseif(!empty($_ENV) && isset($_ENV['HTTP_FORWARDED']))
        {
        $HTTP_FORWARDED = $_ENV['HTTP_FORWARDED'];
        }
    elseif(!empty($HTTP_SERVER_VARS) && isset($HTTP_SERVER_VARS['HTTP_FORWARDED']))
        {
        $HTTP_FORWARDED = $HTTP_SERVER_VARS['HTTP_FORWARDED'];
        }
    elseif(!empty($HTTP_ENV_VARS) && isset($HTTP_ENV_VARS['HTTP_FORWARDED']))
        {
        $HTTP_FORWARDED = $HTTP_ENV_VARS['HTTP_FORWARDED'];
        }
    elseif(@getenv('HTTP_FORWARDED'))
        {
        $HTTP_FORWARDED = getenv('HTTP_FORWARDED');
        }
    } // end if
if(empty($HTTP_VIA))
    {
    if(!empty($_SERVER) && isset($_SERVER['HTTP_VIA']))
        {
        $HTTP_VIA = $_SERVER['HTTP_VIA'];
        }
    elseif(!empty($_ENV) && isset($_ENV['HTTP_VIA']))
        {
        $HTTP_VIA = $_ENV['HTTP_VIA'];
        }
    elseif(!empty($HTTP_SERVER_VARS) && isset($HTTP_SERVER_VARS['HTTP_VIA']))
        {
        $HTTP_VIA = $HTTP_SERVER_VARS['HTTP_VIA'];
        }
    elseif(!empty($HTTP_ENV_VARS) && isset($HTTP_ENV_VARS['HTTP_VIA']))
        {
        $HTTP_VIA = $HTTP_ENV_VARS['HTTP_VIA'];
        }
    elseif(@getenv('HTTP_VIA'))
        {
        $HTTP_VIA = getenv('HTTP_VIA');
        }
    } // end if
if(empty($HTTP_X_COMING_FROM))
    {
    if(!empty($_SERVER) && isset($_SERVER['HTTP_X_COMING_FROM']))
        {
        $HTTP_X_COMING_FROM = $_SERVER['HTTP_X_COMING_FROM'];
        }
    elseif(!empty($_ENV) && isset($_ENV['HTTP_X_COMING_FROM']))
        {
        $HTTP_X_COMING_FROM = $_ENV['HTTP_X_COMING_FROM'];
        }
    elseif(!empty($HTTP_SERVER_VARS) && isset($HTTP_SERVER_VARS['HTTP_X_COMING_FROM']))
        {
        $HTTP_X_COMING_FROM = $HTTP_SERVER_VARS['HTTP_X_COMING_FROM'];
        }
    elseif(!empty($HTTP_ENV_VARS) && isset($HTTP_ENV_VARS['HTTP_X_COMING_FROM']))
        {
        $HTTP_X_COMING_FROM = $HTTP_ENV_VARS['HTTP_X_COMING_FROM'];
        }
    elseif(@getenv('HTTP_X_COMING_FROM'))
        {
        $HTTP_X_COMING_FROM = getenv('HTTP_X_COMING_FROM');
        }
    } // end if
if(empty($HTTP_COMING_FROM))
    {
    if(!empty($_SERVER) && isset($_SERVER['HTTP_COMING_FROM']))
        {
        $HTTP_COMING_FROM = $_SERVER['HTTP_COMING_FROM'];
        }
    elseif(!empty($_ENV) && isset($_ENV['HTTP_COMING_FROM']))
        {
        $HTTP_COMING_FROM = $_ENV['HTTP_COMING_FROM'];
        }
    elseif(!empty($HTTP_COMING_FROM) && isset($HTTP_SERVER_VARS['HTTP_COMING_FROM']))
        {
        $HTTP_COMING_FROM = $HTTP_SERVER_VARS['HTTP_COMING_FROM'];
        }
    elseif(!empty($HTTP_ENV_VARS) && isset($HTTP_ENV_VARS['HTTP_COMING_FROM']))
        {
        $HTTP_COMING_FROM = $HTTP_ENV_VARS['HTTP_COMING_FROM'];
        }
    elseif(@getenv('HTTP_COMING_FROM'))
        {
        $HTTP_COMING_FROM = getenv('HTTP_COMING_FROM');
        }
    } // end if
// Gets the default ip sent by the user
if(!empty($REMOTE_ADDR))
    {
    $direct_ip = $REMOTE_ADDR;
    }
// Gets the proxy ip sent by the user
$proxy_ip='';
if(!empty($HTTP_X_FORWARDED_FOR))$proxy_ip = $HTTP_X_FORWARDED_FOR;
elseif(!empty($HTTP_X_FORWARDED))$proxy_ip = $HTTP_X_FORWARDED;
elseif(!empty($HTTP_FORWARDED_FOR))$proxy_ip = $HTTP_FORWARDED_FOR;
elseif(!empty($HTTP_FORWARDED))$proxy_ip = $HTTP_FORWARDED;
elseif(!empty($HTTP_VIA))$proxy_ip = $HTTP_VIA;
elseif(!empty($HTTP_X_COMING_FROM))$proxy_ip = $HTTP_X_COMING_FROM;
elseif(!empty($HTTP_COMING_FROM))$proxy_ip = $HTTP_COMING_FROM;
// Returns the true IP if it has been found, else FALSE
if (empty($proxy_ip))
    {
    // True IP without proxy
    return $direct_ip;
    }
else
    {
    $is_ip = ereg('^([0-9]{1,3}\.){3,3}[0-9]{1,3}', $proxy_ip, $regs);
    if($is_ip && (count($regs) > 0))
        {
        // True IP behind a proxy
        return $regs[0];
        }
    else
        {
        // Can't define IP: there is a proxy but we don't have
        // information about the true IP
        return FALSE;
        }
    } // end if... else...
}
Dan
  • 55,715
  • 40
  • 116
  • 154
  • How do I call the funtion? Or display an output. –  Feb 22 '11 at 23:54
  • the return value is of the same type/structure as `$_SERVER['REMOTE_ADDR']`. You can even write `$_SERVER['REMOTE_ADDR'] = get_ip()` at the beginning of the application, and it will work correctly! – Dan Feb 24 '11 at 06:25
  • from 2021 perspective, looks like hell ) – jekaby Mar 19 '21 at 18:22