nginx配置X-Forwarded-For 防止伪造ip

网上常见nginx配置ip请求头

  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

风险: 用户可以通过自己设置请求头来伪造ip,比如用户在发起http请求是自己测试请求头x-forwarded-for:192.168.0.151。那么服务器通过x-forwarded-for获取到的第一个ip就是用户伪造的ip。

  防止伪造方案:

  情况1: 在只有1层nginx代理的情况下,设置nginx配置“proxy_set_header X-Forwarded-For $remote_addr;”。(此时$remote_addr获取的是用户的真是ip)

  情况2:在有多层反向代理的情况下,

1)设置“最外层”nginx配置和情况1一样“proxy_set_header X-Forwarded-For $remote_addr;”。

2)除了“最外层”之外的nginx配置“proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;”。

  这样就防止了用户通过伪造请求头来伪造真实ip。后台只需要从x-forwarded-for请求头中取出第一个ip就是用户的真实ip。后面如果有多个ip,就是反向代理的ip

同理:X-Real-IP也差不多。

     不同的是当只有1层nginx代理情况下只需配置“proxy_set_header X-Real-IP $remote_addr;”即可。

     当有多层反向代理时,只在最外层代理设置“proxy_set_header X-Real-IP $remote_addr;”,如果在非最外层设置,则获取到的是反向代理机器的ip

附上代码:

    public static String getIpAddress(HttpServletRequest request) {
        // 从Nginx中x-forwarded-for获取真实ip
        String ipAddress = request.getHeader("X-Forwarded-For");
        if (ipAddress != null && ipAddress.length() > 0 && !"unknown".equalsIgnoreCase(ipAddress)) {
            // 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割

            int index = ipAddress.indexOf(",");
            if (index > 0) {
                ipAddress = ipAddress.substring(0, index).trim();
            }
            return ipAddress;
        }
        // 从Nginx中X-Real-IP获取真实ip
        ipAddress = request.getHeader("X-Real-IP");
        if (ipAddress != null && ipAddress.length() > 0 && !"unknown".equalsIgnoreCase(ipAddress)) {
            return ipAddress;
        }


        ipAddress = request.getRemoteAddr();
        // if ("127.0.0.1".equals(ipAddress) ||
        // "0:0:0:0:0:0:0:1".equals(ipAddress)) {
        // // 根据网卡取本机配置的IP
        // ipAddress = InetAddress.getLocalHost().getHostAddress();
        // }
        return ipAddress;

    }