如何用PHP检测代理[关闭]

Sometimes people use a proxy to mask their real IP address. I don't want this. I want to restrict that user to access my website.

I have build a website in PHP.

You can block proxies using " HTTP HEADERS "

   function shapeSpace_block_proxy_visits() {

     $headers = array('CLIENT_IP','FORWARDED','FORWARDED_FOR','FORWARDED_FOR_IP','VIA','X_FORWARDED','X_FORWARDED_FOR','HTTP_CLIENT_IP','HTTP_FORWARDED','HTTP_FORWARDED_FOR','HTTP_FORWARDED_FOR_IP','HTTP_PROXY_CONNECTION','HTTP_VIA','HTTP_X_FORWARDED','HTTP_X_FORWARDED_FOR');

      foreach ($headers as $header){
         if (isset($_SERVER[$header])) {
             die('Proxy access not allowed.');
         }
      }
   }

2 Ways you can achieve it. These techniques work for any PHP-enabled site, including WordPress, Drupal, Joomla, and many others

1)Block proxy visits via port scanning

function blockproxyvisits() {

$ports = array(80,81,553,554,1080,3128,4480,6588,8000,8080);

foreach ($ports as $port) {
    if (@fsockopen($_SERVER['REMOTE_ADDR'], $port, $errno, $errstr, 5)) {
        die('Proxy access not allowed.');
    }
} }

2)Block proxy visits via HTTP headers

function blockproxy_visits() {

$headers = array('CLIENT_IP','FORWARDED','FORWARDED_FOR','FORWARDED_FOR_IP','VIA','X_FORWARDED','X_FORWARDED_FOR','HTTP_CLIENT_IP','HTTP_FORWARDED','HTTP_FORWARDED_FOR','HTTP_FORWARDED_FOR_IP','HTTP_PROXY_CONNECTION','HTTP_VIA','HTTP_X_FORWARDED','HTTP_X_FORWARDED_FOR');

foreach ($headers as $header){
    if (isset($_SERVER[$header])) {
        die('Proxy access not allowed.');
    }
} }

The downside here is that scanning for open ports requires more time than simply checking for HTTP headers

It is safer and more efficient to do most sentry work at the perimeter (Web Server Access Control) rather than the front door (PHP).

Checking HTTP header: If you are using PHP, I assume can also edit .htaccess and it is better to block there:

# block proxy servers from site access
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]

Above is from https://perishablepress.com/press/2008/04/20/how-to-block-proxy-servers-via-htaccess/) you can extend with other header checks as required. N.B. if you are using a hosting provider there may be other (e.g. reverse proxy) servers in front of your web server. e.g. an NGINX server might provide visitor IP in 'HTTP_X_REAL_IP', but there is no set standard, so it might provide your non-proxied visitor's IP in one of the headers you are blocking. You can check for this using the PHP code in this (my) article.

Anonymous Proxies: Checking headers won't block those you least want to access your site using anonymous proxies.

As stated in other answer, you can use PHP to check based on port number but comments on a similar answer say its impractical due to slowness, false positives and Malware alerts on client device by some AV packages( rather than your site immediately providing expected response you site "port scans" the clients computer).

If you are using free Cloudflare you can block known TOR (darkweb VPN) exit nodes identified as "T1".

By chance I discovered that my host provided server included IP Geolocation. If your Apache or Litespeed server is using mod_geoip with up to date Maxmind data then GEOIP_COUNTRY_CODE == "A1" indicates a known anonymous proxy. Also, when I checked a year ago Operas free VPN was always identified as "EU" whichever continent was selected in browser. Maxmind uses "EU" for some IP addresses known to be European but not identified to a country - so this will result in some false positives.

htaccess:

# block TOR if using Cloudflare
RewriteEngine on
RewriteCond %{HTTP:CF-IPCountry} ^(T1)$
RewriteRule .* - [F]

#if you server sets GEOIP_COUNTRY_CODE
GeoIPEnable On
# checks for Anonymous Proxy and Opera VPN
SetEnvIf GEOIP_COUNTRY_CODE A1 isProxy
SetEnvIf GEOIP_COUNTRY_CODE EU isProxy
Allow from all  
Deny from env=isProxy

Or PHP:

// if server mod_geoip installed
if ( !empty( $_SERVER['GEOIP_COUNTRY_CODE'] == 'A1') die('Proxy not allowed');
// or if using Cloudflare
if ( !empty($_SERVER["HTTP_CF_IPCOUNTRY"] && $_SERVER["HTTP_CF_IPCOUNTRY"] == 'T1') die('Tor not allowed');

If your server does not have mod_geoip but you are already using "Maxmind for PHP" to look up country codes you could modify your scripts IP to country code look-up and die if code is "A1".