1

我使用以下代码来检测用户是否在代理/vpn 后面:

function checkUser()
{
    $proxy = null;
    $check = null;
    $proxy = ($_SERVER['HTTP_ACCEPT_ENCODING'] != 'gzip, deflate') ? true : false;
    if(empty($_SERVER['HTTP_CONNECTION']) || strtolower($_SERVER['HTTP_CONNECTION']) != 'keep-alive' || $_SERVER['HTTP_CACHE_CONTROL'] != 'max-age=0')
    {
        $check = ($proxy === true) ? 'proxy' : 'vpn';
    }
    return $check;
}
$connection = checkUser();
switch($connection)
{
    case 'proxy': $var = 'It seems you are behind Proxy.'; break;
    case 'vpn': $var = 'It seems you are using VPN.'; break;
    default: $var = 'No Proxy or VPN detected.'; break;
}
echo $var;

但是,它在我拥有的旧服务器上运行良好,但在新服务器上却不行。新服务器正在使用反向代理服务器 (nginx)。有人可以告诉我它是否与 nginx 有关,以及我应该在配置中调整什么。谢谢!

- - 编辑: - -

#user  nginx;
worker_processes  4;
worker_rlimit_nofile 950000;


#error_log  /var/log/nginx/error.log;
#error_log  /var/log/nginx/error.log  notice;
#error_log  /var/log/nginx/error.log  info;

#pid        /var/run/nginx.pid;


events {
    worker_connections  45000;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  5;
    #tcp_nodelay        on;

    #gzip  on;
    #gzip_disable "MSIE [1-6]\.(?!.*SV1)";

    server_tokens off;

    include /etc/nginx/conf.d/*.conf;

        fastcgi_buffers 8 16k;
        fastcgi_buffer_size 32k;
        fastcgi_connect_timeout 300;
        fastcgi_send_timeout 300;
        fastcgi_read_timeout 300;
}
4

1 回答 1

1

您的代码似乎基于代理将禁用 gzip/deflate 和/或保持活动会话的使用的假设。这不是一个准确的假设。如果这些功能被关闭,实现代理会更容易,但根据规范,没有什么可以阻止代理在这些功能开启时正常工作。

所以是的,nginx 可能只是一个更好的代理,所以上面代码的作者所做的假设现在是错误的。

检查 HTTP 代理的正确方法是查找是否存在 X-Forwarded-For 标头。这样的事情就足够了:

function isProxied() {
    $headers = array_change_key_case(apache_request_headers());
    return isset($headers["x-forwarded-for"]);
}

从技术上讲,可以在不宣传它的存在的情况下实现代理(不添加 X-Forwarded-For 标头) - 有些人可以选择这样做,在这种情况下,您将无法真正检测到这一点。但是大多数代理都会与您合作。

请注意,如果您在自己的服务器堆栈中使用代理(即,如果您在 Apache 前面运行 Varnish、Nginx 或其他东西),那么这也可能会添加一个 X-Forwarded-For 标头,所以一切似乎都被代理了(基于此,看起来nginx默认使用“X-Real-IP”,所以你可能不需要担心这个)。如果是这种情况,请关闭 Varnish/Nginx/whatever 中的该选项,或者解析 X-Forwarded-For 标头以查看那里是否有两个 IP,而不是一个。

关于 VPN 连接,我认为您不会找到一种可靠的方法来检测用户是否仅通过传入的 HTTP 连接使用 VPN。尽管您可能会考虑检查他的原始 IP 以查看他是否来自已知的 TOR 地址或类似的东西。取决于你对它的关心程度。

于 2013-09-30T04:34:21.967 回答