Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

防止X-Forwarded-For伪造客户端IP漏洞,获取真实IP方法 #45

Open
dalaolala opened this issue Jun 4, 2022 · 0 comments
Open

Comments

@dalaolala
Copy link
Owner

HTTP协议是基于TCP协议的,由于getenv('REMOTE_ADDR')获取到的是TCP层直接连接的客户端的IP,对于Web应用服务器来说直接连接它的客户端实际上是Nginx,也就是TCP层是拿不到真实客户端的IP。

为了解决上面的问题,很多HTTP代理会在HTTP协议头中添加X-Forwarded-For头,用来追踪请求的来源。X-Forwarded-For的格式如下:

X-Forwarded-For: client1, proxy1, proxy2

php版本的代码如下

function get_ip()
    {
        $onlineip = '';
        if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
            $onlineip = getenv('HTTP_CLIENT_IP');
        } elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
            $onlineip = getenv('HTTP_X_FORWARDED_FOR');
        if (getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
            $onlineip = getenv('REMOTE_ADDR');
        } elseif (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
            $onlineip = $_SERVER['REMOTE_ADDR'];
        }
        return $onlineip;
    }

在直接对外的Nginx反向代理服务器上配置:

proxy_set_header X-Forwarded-For $remote_addr;

这里使用$remote_addr替代上面的$proxy_add_x_forwarded_for。$proxy_add_x_forwarded_for会在原有X-Forwarded-For上追加IP,这就相当于给了伪造X-Forwarded-For的机会。而$remote_addr是获取的是直接TCP连接的客户端IP(类似于Java中的request.getRemoteAddr()),这个是无法伪造的,即使客户端伪造也会被覆盖掉,而不是追加。

需要注意的是,如果有多层代理,那么只要在直接对外访问的Nginx上配置X-Forwarded-For为$remote_addr,内部层的Nginx还是要配置为$proxy_add_x_forwarded_for,不然内部层的Nginx又会覆盖掉客户端的真实IP。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant