博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
阿里云CDN + nginx多级代理获取客户端IP
阅读量:7107 次
发布时间:2019-06-28

本文共 3118 字,大约阅读时间需要 10 分钟。

无Nginx代理场景

业务层通过获取请求头参数即可拿到客户端IP

request.getRemoteAddr();复制代码

一级Nginx代理

使用代理后直接读取请求头参数会读取到代理服务器的IP地址,而非真实客户端IP

解决方法是添加Nginx请求头参数提前保存客户端IP

nginx.conf配置加入内容

location / {    ...    # IP地址转发    proxy_set_header X-Real-IP $remote_addr;    proxy_set_header X-Real-Port $remote_port;    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  }复制代码

业务层读取nginx配置的请求头参数即可

public static String getIpAddr(HttpServletRequest request) {        String ip = request.getHeader("X-Real-IP");        if (ip == null || ip.length() == 0 || " unknown ".equalsIgnoreCase(ip)) {            ip = request.getHeader("Proxy-Client-IP");            log.info("【Proxy-Client-IP】 {}", ip);        }        if (ip == null || ip.length() == 0 || " unknown ".equalsIgnoreCase(ip)) {            ip = request.getHeader("WL-Proxy-Client-IP");            log.info("【WL-Proxy-Client-IP】{}", ip);        }        if (ip == null || ip.length() == 0 || " unknown ".equalsIgnoreCase(ip)) {            ip = request.getHeader("X-Forwarded-For");            log.info("【X-Forwarded-For】{}", ip);        }        if (ip == null || ip.length() == 0 || " unknown ".equalsIgnoreCase(ip)) {            ip = request.getRemoteAddr();            log.info("【unknown】{}", ip);        }        return ip;    }复制代码

多级Nginx代理

若存在多级Nginx代理,则需要在第一级代理时获取客户端IP,在后续代理逐层传递

第一级代理配置同上,第N级代理配置nginx.conf如下

location /{   # IP地址转发   proxy_set_header X-Real-IP $X-Real-IP;   proxy_set_header X-Real-Port $X-Real-Port;   proxy_set_header X-Forwarded-For $X-Forwarded-For;}复制代码

业务层保持不变即可读取到传递的IP地址

阿里云CDN转发

在已经存在nginx代理的场景下,加入CDN后源客户端IP在CDN处被转发,故第一级nginx代理使用$remote_addr参数读取到的是CDN服务的地址,而根据一般约定,CDN转发会将IP地址存放在X-Forwarded-For参数下

修改顶级Nginx配置以支持优先获取CDN代理地址,也可以通过修改业务层读取优先级实现

location / {    ...    # IP地址转发    # proxy_set_header X-Real-IP $remote_addr;    # proxy_set_header X-Real-Port $remote_port;    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  }复制代码

但经过对阿里云CDN测试,发现X-Forwarded-For下不仅包含真实客户端IP也包含CDN服务IP,故业务层需要做一定的处理进行区分

如图,第一个为真实客户端IP,第二个为CDN代理IP

public static String getIpAddr(HttpServletRequest request) {        String ip = request.getHeader("X-Real-IP");        if (ip == null || ip.length() == 0 || " unknown ".equalsIgnoreCase(ip)) {            ip = request.getHeader("Proxy-Client-IP");            log.info("【Proxy-Client-IP】 {}", ip);        }        if (ip == null || ip.length() == 0 || " unknown ".equalsIgnoreCase(ip)) {            ip = request.getHeader("WL-Proxy-Client-IP");            log.info("【WL-Proxy-Client-IP】{}", ip);        }        if (ip == null || ip.length() == 0 || " unknown ".equalsIgnoreCase(ip)) {            ip = request.getHeader("X-Forwarded-For");            if (ip.contains(",")) {                // 通过阿里云CDN转发后可能读取到2个IP地址                String[] cdnMutilIp = ip.split(",");                ip = cdnMutilIp[0];            }            log.info("【X-Forwarded-For】{}", ip);        }        if (ip == null || ip.length() == 0 || " unknown ".equalsIgnoreCase(ip)) {            ip = request.getRemoteAddr();            log.info("【unknown】{}", ip);        }        return ip;    }}复制代码

转载于:https://juejin.im/post/5ca4155ce51d45507547b47a

你可能感兴趣的文章
5年麦肯锡工作经验的GG总结的Word骨灰级操作大全
查看>>
Xcode下载
查看>>
python operator计算模块
查看>>
SVN版本冲突解决详解
查看>>
nginx rewrite规则
查看>>
浅谈javascript:void(0)的含义
查看>>
IOS学习动画一之 UIKit动画
查看>>
tomcat编码乱码问题
查看>>
Spring中的自动装配(AutoWire)
查看>>
016,spring boot集成Mybatis之多数据源
查看>>
关于JOptionPane的一些东西
查看>>
STM32学习笔记2——RC522
查看>>
Centos环境下的DNS智能解析
查看>>
文件扩展名(后缀)与MINE-type的对照关系
查看>>
linux启动jmeter报An error occurred
查看>>
华为设备工作中常用到的nat server配置
查看>>
RabbitMQ学习总结(6)——消息的路由分发机制详解
查看>>
haproxy的stats管理和负载均衡mysql的实例
查看>>
Spring常用注解
查看>>
Java基础学习总结(11)——重载与重写
查看>>