负载均衡后获取客户端真实ip

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wudinaniya/article/details/84583305

String ip3=request.getRemoteAddr(); 如果没有配负载均衡,则request.getRemoteAddr() 获取的就是真实客户端IP,如果配了nginx负载均衡,则request.getRemoteAddr() 获取的是负载均衡nginx服务器的ip,而不是真实客户端IP。

那么问题来了,经过nginx负载均衡后,如何获取客户端真实ip?

location / {
    root   html;
    index  index.html index.htm;
    
    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://192.168.81.188:8080;
}
 

代码中,Header中使用“X-Forwarded-For”字段或“X-Real-IP”字段获取Client真实 IP。

以一个servlet为例:
 

​​​​​​​    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        //response.getWriter().append("Served at: ").append(request.getContextPath());
        
        PrintWriter writer = response.getWriter();
        //也可以使用小写的字段 String ip=request.getHeader("x-forwarded-for");
        String ip=request.getHeader("X-Forwarded-For");
        writer.println("x-forwarded-for_ip:  "+ip);

        //也可以使用小写的字段 String ip2=request.getHeader("x-real-ip");
        String ip2=request.getHeader("X-Real-IP");
        writer.println("x-real-ip:  "+ip2);

        String ip3=request.getRemoteAddr();
        writer.println("RemoteAddr:  "+ip3);
        
        
    }

注意:从Header中获取字段的时候,是不区分大小写的。所以 request.getHeader("x-forwarded-for")和request.getHeader("X-Forwarded-For")以及request.getHeader("x-FORWARded-for")效果是一样的。

如果通过了多级反向代理的话,X-Forwarded-For的值不止一个,而是一串IP值,此时取第一个IP地址就可以了,第一个IP代表客户端真实IP,比如:

分析:
从CSN开始,每经过一个代理做一次转发,x_forwarded_for就会在后面追加一个代理IP。请求到达nginx时,x_forwarded_for已经变成一个以逗号分隔的ip串,并且以转发顺序排序。
nginx的内置变量remote_addr()仅能代表nginx的上一层代理的IP,现有的nginx配置将该值赋给X_Real_IP,那么后端获取到的X_Real_IP只是nginx上一层代理的IP,而不是客户端真实的IP。

举例:如图,我经过两层代理,最终到达后端真实业务服务器:

浏览器访问结果:

猜你喜欢

转载自blog.csdn.net/wudinaniya/article/details/84583305