多层代理 获取真实IP 问题

多层代理 获取真实IP 问题百度一搜 一堆. 但大多都是通过 X-Forwarded-For 获取真实IP
原理就是 负载 LVS /EOB /SLB 为了让下游正常获取 客户端IP 会将 客户端IP 填充到 X-Forwarded-For 中传递给下游服务

用户真实IP, 负载, 代理服务器1-IP, 代理服务器2-IP

我们原来获取真实IP 直接就 逗号炸开 取第一个IP

问题来了 客户端请求头 只需要添加 X-Forwarded-For 头信息 就可以伪造IP

解决方案:

  1. 根据自己服务代理层数决定 层数 != ip 数 就丢包

     /**
      * @desc 检测异常IP
      * @return string
      * @throws
      * ------------------------------------------------------------
      */
     public static function checkLimitIp()
     {
         $header_data = Http::getHeader();
         foreach (array('x-real-forwarded-for', 'x-forwarded-for', 'http_x_forwarded_for', 'x-real-ip', 'http_client_ip', 'remote_addr') as $v1) {
             if (isset($header_data[$v1])) {
                 $ip_list = explode(',', $header_data[$v1]);
                 // todo 注意 前端 slb + nginx IP
                 $ip_num = count($ip_list);
                 if ($ip_num > 2) {
                     throw new ErrorException(-114);
                 }
             }
         }
     }
    
  2. 代理层除了第一层负载外 全部都是内网IP 所以只需要倒着数 找到最后一个外网IP 就可以定位到 负载IP , 负载IP 的前面就是真实客户端IP

真实深坑. 阿里云SLB 如果是覆盖 X-Forwarded-For , 不是 追加 X-Forwarded-For 就不会存在用户伪造问题. 也许阿里大佬有自己的想法吧 . 但在业务代码中 过滤真心麻烦....

发表新评论