美文网首页
laravel获取nginx代理后的客户真实IP

laravel获取nginx代理后的客户真实IP

作者: gao922699 | 来源:发表于2022-08-15 00:02 被阅读0次

    问题:

    用Laravel的$request->getClientIp()方法获取IP,

    1. 本机nginx proxy 获取到的是docker网络的Ip地址,类似172.17.0.1之流(docker创建的网络,本机的IP不是127.0.0.1)

    2. 另外一台机器用nginx proxy 获取到的是机器本身的外网IP

    都无法获取客户的真实访问IP

    原因:

    查看laravel的getClientIp方法源码

    public function getClientIps()
    {
        $clientIps = array();
        $ip = $this->server->get('REMOTE_ADDR');
    
        if (!$this->isFromTrustedProxy()) {
            return array($ip);
        }
    
        $hasTrustedForwardedHeader = self::$trustedHeaders[self::HEADER_FORWARDED] && $this->headers->has(self::$trustedHeaders[self::HEADER_FORWARDED]);
        $hasTrustedClientIpHeader = self::$trustedHeaders[self::HEADER_CLIENT_IP] && $this->headers->has(self::$trustedHeaders[self::HEADER_CLIENT_IP]);
    
        if ($hasTrustedForwardedHeader) {
            $forwardedHeader = $this->headers->get(self::$trustedHeaders[self::HEADER_FORWARDED]);
            preg_match_all('{(for)=("?\[?)([a-z0-9\.:_\-/]*)}', $forwardedHeader, $matches);
            $forwardedClientIps = $matches[3];
    
            $forwardedClientIps = $this->normalizeAndFilterClientIps($forwardedClientIps, $ip);
            $clientIps = $forwardedClientIps;
        }
    
        if ($hasTrustedClientIpHeader) {
            $xForwardedForClientIps = array_map('trim', explode(',', $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_IP])));
    
            $xForwardedForClientIps = $this->normalizeAndFilterClientIps($xForwardedForClientIps, $ip);
            $clientIps = $xForwardedForClientIps;
        }
    
        if ($hasTrustedForwardedHeader && $hasTrustedClientIpHeader && $forwardedClientIps !== $xForwardedForClientIps) {
            throw new ConflictingHeadersException('The request has both a trusted Forwarded header and a trusted Client IP header, conflicting with each other with regards to the originating IP addresses of the request. This is the result of a misconfiguration. You should either configure your proxy only to send one of these headers, or configure Symfony to distrust one of them.');
        }
    
        if (!$hasTrustedForwardedHeader && !$hasTrustedClientIpHeader) {
            return $this->normalizeAndFilterClientIps(array(), $ip);
        }
    
        return $clientIps;
    }
    

    1. remote_addr的值在经过proxy后变成了进行proxy的机器的ip,不再是客户真实的ip了;

    2. isFromTrustedProxy判断了proxy的remote_addr,要把remote_addr写入白名单;

    3. 经过proxy的ip获取的是X-Forwarded-For的值;

    解决办法:

    1. nginx设置X-Forwarded-For
    server {
            listen 80;
            server_name  www.XXXXX.cn;
            location / {
                proxy_pass http://XX.XX.XX.XX;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            }
    }
    
    1. laravel添加TrustedProxy

    通过Request::setTrustedProxies()方法设置;传入ip数组

    可以是掩码的格式,例如:

    [
        "172.17.0.1/16",
        "156.132.44.23"
    ]
    

    相关文章

      网友评论

          本文标题:laravel获取nginx代理后的客户真实IP

          本文链接:https://www.haomeiwen.com/subject/izgawrtx.html