使用nginx作为代理之后,如何配置可以得到用户的真实ip地址?

你的笑靥 发表于: 2020-04-17   最后更新时间: 2020-04-17 17:02:08   2,439 游览

如标题所述

  1. 服务器使用的是ubuntu16.04,nginx版本为1.10.3

  2. 在代码中通过request去尝试获取ip地址,但是获取到的是服务器的ip或者是服务器的网关地址

    String addr = httpServletRequest.getRemoteAddr();    //addr的值获取到之后为服务器本地的地址    192.168.68.128
    String forwarded = httpServletRequest.getHeader("X-Forwarded-For");    //此时这个值获取到之后是服务器的网关地址    192.168.68.1
    //使用自己写的工具类通过获取请求头"X-Forwarded-For"的值获取到的也是服务器的网关地址    192.168.68.1
    
  3. 我在nginx的配置文件default中location配置块中配置信息如下:

    proxy_set_header  Host $http_host;
    proxy_set_header  X-Real-IP $remote_addr;
    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Proto $scheme;
    
  1. 我现在想得到是用户在别处通过页面请求服务时可以得到用户自己的ip地址,而不是nginx部署机器的ip地址.我该改进哪里呢?
发表于 2020-04-17
¥2.0

nginx配置没问题。

// 配置此处用于获取客户端的真实IP
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://localhost:8080;

java获取地方你改改,网上比较流行的

package com.moyutang.common.utils;
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;

public class IpUtil {
    public static String getIpAddr(HttpServletRequest request) {
        String ipAddress = null;
        try {
            ipAddress = request.getHeader("x-forwarded-for");
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getRemoteAddr();
                if (ipAddress.equals("127.0.0.1")) {
                    // 根据网卡取本机配置的IP
                    InetAddress inet = null;
                    try {
                        inet = InetAddress.getLocalHost();
                    } catch (UnknownHostException e) {
                        e.printStackTrace();
                    }
                    ipAddress = inet.getHostAddress();
                }
            }
            // 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
            if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length()
                // = 15
                if (ipAddress.indexOf(",") > 0) {
                    ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
                }
            }
        } catch (Exception e) {
            ipAddress="";
        }
        return ipAddress;
    }
}
你的笑靥 -> 半兽人 4年前

实不相瞒,这个工具类就是我现在正在使用的工具类,我在代码中使用工具类获取到的ip地址和String forwarded = httpServletRequest.getHeader("X-Forwarded-For"); 这句代码获取到的ip地址是一样的.

半兽人 -> 你的笑靥 4年前

需要启动ngx_http_realip_module模块,默认这个模块没有启动,需要在安装时使用--with-http_realip_module作为configuration的参数。

你的笑靥 -> 半兽人 4年前

请问是在安装nginx的时候吗?

半兽人 -> 你的笑靥 4年前

嗯,如果你已经安装过了,要重新编译,替换现有的nginx。

你的笑靥 -> 半兽人 4年前

您好,请问您有通过源码编译来安装nginx的教程吗?我在网上找的文档都不能成功安装

你的笑靥 -> 半兽人 4年前

半兽人大佬,请问还有别的方法能获取到代理转发之后的ip吗(#o.o汗).我用您说的这种方法得到的ip和之前的效果是一样的.

半兽人 -> 你的笑靥 4年前

汗…不科学呀 你验证过配置都生效了么

你的笑靥 -> 半兽人 4年前
/opt/nginx/sbin/nginx -t

检测配置文件,得到的结果为:

nginx: the configuration file /opt/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /opt/nginx/conf/nginx.conf test is successful

nginx.conf中配置内容为:

            root   /opt/nginx/html/dist;
            index  index.html index.htm;
location /dist/ {
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_pass http://localhost:8080;
       }

访问 http://192.168.68.128 可以正常访问.
代码中打印请求头,部分信息如下:

referer为:http://192.168.68.128/
x-forwarded-host为:192.168.68.128:9001
x-forwarded-for为:192.168.68.1
host为:192.168.68.128:7008

这样配置应该没啥问题了吧.

半兽人 -> 你的笑靥 4年前
/opt/nginx/sbin/nginx -V

看看

你的笑靥 -> 半兽人 4年前

得到信息如下:

nginx version: nginx/1.8.1
built by gcc 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.12) 
built with OpenSSL 1.0.1i 6 Aug 2014
TLS SNI support enabled
configure arguments: --prefix=/opt/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_gzip_static_module --with-http_stub_status_module --with-http_realip_module --pid-path=/var/run/nginx.pid --with-pcre=/opt/software/pcre-8.35 --with-zlib=/opt/software/zlib-1.2.11 --with-openssl=/opt/software/openssl-1.0.1i
半兽人 -> 你的笑靥 4年前

试试用set_real_ip_from,参考
https://www.orchome.com/8168

你的笑靥 -> 半兽人 4年前

大佬,是不是我配置文件有问题啊?当我在nginx.conf中这么配置的时候

server {
    listen       8080;
    server_name  localhost; 
    location / {
            root   /opt/nginx/html/dist;
            index  index.html index.htm;
            proxy_set_header remote-user-ip $remote_addr;
            proxy_set_header Host $http_host;  
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_pass http://localhost:8080/;

或者是

# proxy_pass http://localhost:8080;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
}

打开主页 http://192.168.68.128:8080/ 页面报 500 Internal Server Error
去看error.log中查看提示打开太多文件

2020/04/23 10:22:04 [crit] 3724#0: accept4() failed (24: Too many open files)
2020/04/23 10:22:04 [crit] 3724#0: accept4() failed (24: Too many open files)
2020/04/23 10:22:05 [crit] 3724#0: accept4() failed (24: Too many open files)
2020/04/23 10:22:05 [alert] 3724#0: *12352 socket() failed (24: Too many open files) while connecting to upstream, client: 127.0.0.1, server: localhost, request: "GET / HTTP/1.0", upstream: "http://127.0.0.1:8080/", host: "192.168.68.128:8080"
2020/04/23 10:22:05 [crit] 3724#0: *12352 open() "/opt/nginx/html/50x.html" failed (24: Too many open files), client: 127.0.0.1, server: localhost, request: "GET / HTTP/1.0", upstream: "http://127.0.0.1:8080/", host: "192.168.68.128:8080"

可是我确定只有我一人在访问.
当我把location / {}配置块中的proxy_pass指令去掉之后可以正常访问http://192.168.68.128:8080/.

是不是我的配置出了问题

半兽人 -> 你的笑靥 4年前

变成了反复的访问自己了,你监听的是8080,跳转的又是8080

你的笑靥 -> 半兽人 4年前

我把proxy_pass指令去掉之后是可以的,这个时候算是已经加载了location / {}配置块了吗?

半兽人 -> 你的笑靥 4年前

嗯,已经加载了。

你的笑靥 -> 半兽人 4年前

大佬,我还是想问一下,既然加载了为什么我的请求头中没有xff这个字段呢,我最终的IP获取是从工具类中
ipAddress = request.getRemoteAddr();
这句代码中获取到的.

半兽人 -> 你的笑靥 4年前

你是通过“proxy_set_header X-Real-IP $remote_addr”把真实客户端IP写入到请求头X-Real-IP,所以你使用“$remote_addr”可以获取到真实的ip。

你的答案

查看nginx相关的其他问题或提一个您自己的问题