获取客户端调用IP地址-使用nginx做反向代理的场景

478 阅读3分钟

nginx修改配置以获取客户端调用IP地址

背景
  • 由于最近业务需求需要对接口调用方进行验签,在验签流程中需要判断客户端请求的IP地址是否合法
获取客户端IP地址
  • 使用HttpServletRequest中的getRemoteAddr()方法,但是由于项目中使用了nginx来做反向代理,所以我们拿到的是反向代理服务器的地址-也就是服务部署的地址

  • 在实际应用中,客户端发送请求时,通常会经过多个网络中间设备,例如代理服务器、负载均衡器等。由于每个中间设备都会添加自己的请求头信息,从而可能覆盖原始请求的IP地址信息。这时,反向代理服务器在接收到请求后,需要根据所使用的协议(如HTTP协议)中定义的特定请求头字段,正确提取客户端真实IP地址 常用的请求头字段:

    • X-Forwarded-For: 通常由反向代理服务器添加,用于标识请求的真实客户端IP地址。它是一个逗号分隔的IP地址列表,列表的第一个IP地址是客户端真实IP地址,其后的IP地址是经过代理的IP地址
    • Proxy-Client-IP: 代理服务器可能添加的字段,也用于标识客户端真实IP地址
    • WL-Proxy-Client-IP: WebLogic服务器可能添加的字段,也用于标识客户端真实IP地址
    • HTTP_CLIENT_IPHTTP_X_FORWARDED_FOR: 类似于 Proxy-Client-IP,可能由代理服务器添加

    因此我们根据上述请求头中对应的字段来获取客户端请求的真实IP

    示例代码:

    // 上述请求头字段
    private static final Set<String> headerName = new HashSet<>(Arrays.asList(
                "X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR"));
    // 获取IP地址方法
    private String getRealIpAddress(HttpServletRequest request) {
        // 请求头字段
        for (String header : headerName) {
            String ipAddress = request.getHeader(header);
            if (StrUtil.isNotBlank(ipAddress) && !"unknown".equalsIgnoreCase(ipAddress)) {
                // 代理服务器可能添加多个代理地址,取第一个
                return ipAddress.split(",")[0].trim();
            }
        }
        return request.getRemoteAddr();
    }
    
nginx配置

上面我们通过getRealIpAddress方法拿到的仍然是对应服务部署的地址,当我看到日志中打印的IP地址的时候也是满头雾水,经过一番搜索才发现在nginx的反向代理配置中需要手动配置上面的请求头信息

对应配置

location /对应服务/ {
    proxy_pass 对应的后端服务地址;
    // 下面就是我们需要添加的请求头信息
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header REMOTE-HOST $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

这里我们主要关注X-Forwarded-For字段,OK,现在我们就能拿到客户端请求的IP地址了

notes

其实严格来说我们是拿不到客户端的真实IP地址的,因为上述请求头字段都是可以人为的进行添加和篡改。但是对请求做IP地址限制还是可行的,因为IP地址白名单由服务端来管理,做好保密即可

配置nginx环境变量

上面我们修改了nginx的配置,可以通过nignx对应的命令来检查nginx的配置语法是否正确(nginx -t),以及重启nginx(nginx -s reload)

问题

当输入nginx -t命令检查配置文件的语法时发现提示信息为:nginx:command not found,当替换命令为/usr/local/nginx/sbin/nginx -t时就能正常执行,这时就需要配置nignx的环境变量

步骤
  • 进入etc/profile文件vi etc/profile
  • 添加环境变量:export PATH=$PATH:/usr/local/nginx/sbin // nginx对应的路径
  • 重新加载配置文件:source /etc/profile

现在就可以直接使用nginx -tnignx -s reload等nginx相关命令啦

菜鸟一枚,如有错误敬请指正