如何使用HTTP_X_FORWARDED_FOR正常吗?(How to use HTTP_X_FOR

2019-06-26 05:34发布

好吧,我有一个小的鉴定问题。 我的网络服务允许在同一个用户名和密码的HTTP连接到我的API,但是这种连接也被限制到特定的IP地址。

这意味着, $_SERVER['REMOTE_ADDR']可能不正确。 我已经知道任何IP信息可从来没有真正地依靠 - 我也有限制,只在尝试添加另一层安全。

如果这是我的Web服务器的请求的概述:

clientSERVER => clientPROXY => myPROXY => mySERVER

那么这意味着MYSERVER显示REMOTE_ADDR MYPROXY,而不是客户端的发送客户端的实际IP HTTP_X_FORWARDED_FOR

为了克服这个问题,我的web服务具有“信任代理的IP地址的列表,如果REMOTE_ADDR是从那些值得信赖的IP地址中的一个,那么它告诉我的web服务的实际IP地址的值HTTP_X_FORWARDED_FOR

现在的问题是clientPROXY。 这意味着,(经常)MYSERVER得到HTTP_X_FORWARDED_FOR具有多个IP地址的值。 据HTTP_X_FORWARDED_FOR文件,该值是一个逗号分隔的IP地址列表,其中第一个IP是,实际真正的客户和所有其他IP地址是代理的。

所以,如果HTTP_X_FORWARDED_FOR有多个值,我的服务是IP限制,我必须要检查的“最后”值HTTP_X_FORWARDED_FOR对我的允许的IP列表,只是忽略了实际的客户端IP?

我认为在一个系统,在这里我必须设置允许的IP地址列表,白名单上的IP地址应该是一个代理,而不是一个IP是代理的背后(因为这可能是一些本地主机的IP,并经常变化) 。

和什么HTTP_CLIENT_IP

Answer 1:

您可以使用此功能来获得正确的客户端IP:

public function getClientIP(){       
     if (array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)){
            return  $_SERVER["HTTP_X_FORWARDED_FOR"];  
     }else if (array_key_exists('REMOTE_ADDR', $_SERVER)) { 
            return $_SERVER["REMOTE_ADDR"]; 
     }else if (array_key_exists('HTTP_CLIENT_IP', $_SERVER)) {
            return $_SERVER["HTTP_CLIENT_IP"]; 
     } 

     return '';
}


Answer 2:

我喜欢Hrishikesh的答案,而我只是有这个加...因为我们看到了一个逗号分隔字符串时使用沿途多个代理跨越未来,我们认为有必要增加一个爆炸并抓住最后的值,如这个:

$IParray=array_values(array_filter(explode(',',$_SERVER['HTTP_X_FORWARDED_FOR'])));
return end($IParray);

该array_filter是在里面删除空项。



Answer 3:

在最新的光httpoxy漏洞,实在需要一个完整的例子,如何使用HTTP_X_FORWARDED_FOR正常。

因此,这里是用PHP编写的,如何检测客户端的IP地址,如果你知道客户可能会在代理,你知道这个代理可以信任的一个例子。 如果你不知道任何信任的代理,只需要使用REMOTE_ADDR

<?php

function get_client_ip ()
{
    // Nothing to do without any reliable information
    if (!isset ($_SERVER['REMOTE_ADDR'])) {
        return NULL;
    }

    // Header that is used by the trusted proxy to refer to
    // the original IP
    $proxy_header = "HTTP_X_FORWARDED_FOR";

    // List of all the proxies that are known to handle 'proxy_header'
    // in known, safe manner
    $trusted_proxies = array ("2001:db8::1", "192.168.50.1");

    if (in_array ($_SERVER['REMOTE_ADDR'], $trusted_proxies)) {

        // Get the IP address of the client behind trusted proxy
        if (array_key_exists ($proxy_header, $_SERVER)) {

            // Header can contain multiple IP-s of proxies that are passed through.
            // Only the IP added by the last proxy (last IP in the list) can be trusted.
            $proxy_list = explode (",", $_SERVER[$proxy_header]);
            $client_ip = trim (end ($proxy_list));

            // Validate just in case
            if (filter_var ($client_ip, FILTER_VALIDATE_IP)) {
                return $client_ip;
            } else {
                // Validation failed - beat the guy who configured the proxy or
                // the guy who created the trusted proxy list?
                // TODO: some error handling to notify about the need of punishment
            }
        }
    }

    // In all other cases, REMOTE_ADDR is the ONLY IP we can trust.
    return $_SERVER['REMOTE_ADDR'];
}

print get_client_ip ();

?>


Answer 4:

您也可以使用通过解决Apache配置这个问题mod_remoteip ,加入以下到conf.d文件:

RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 172.16.0.0/12
LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined


Answer 5:

如果您在数据库中使用它,这是一个好办法:

设置IP领域的数据库为varchar(250),然后使用这个:

$theip = $_SERVER["REMOTE_ADDR"];

if (!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) {
    $theip .= '('.$_SERVER["HTTP_X_FORWARDED_FOR"].')';
}

if (!empty($_SERVER["HTTP_CLIENT_IP"])) {
    $theip .= '('.$_SERVER["HTTP_CLIENT_IP"].')';
}

$realip = substr($theip, 0, 250);

然后你只需核对数据库IP字段$ realip



Answer 6:

HTTP_CLIENT_IP是获取用户的IP地址的最可靠的方法。 接下来是HTTP_X_FORWARDED_FOR,其次是REMOTE_ADDR。 检查所有三个,按照这个顺序,假设所设定的第一个( isset($_SERVER['HTTP_CLIENT_IP'])如果变量设置返回true)是正确的。 您可以单独检查,如果用户使用的是不同的方法使用代理。 检查这个出来。



文章来源: How to use HTTP_X_FORWARDED_FOR properly?