项目中Nginx多级代理是如何获取客户端的真实IP地址

多级代理中获取客户端真实IP
日志的格式
nginx中常用日志格式配置如下:

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';
access_log  /var/log/nginx/access.log  main;
1
2
3
4
其中的main为日志格式的别名,在使用的时候直接使用别名即可。

例子:

10.0.3.137 - - [09/Oct/2020:09:41:02 +0800] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko" "10.1.9.98"
1
变量    含义    例子
$remote_addr    客户端的ip地址(直连的IP,代理服务器,显示代理服务ip)    10.0.3.137
$remote_user    用于记录远程客户端的用户名称    -
$time_local    用于记录访问时间和时区    08/Oct/2020:02:37:25 -0400
$request    用于记录请求的url、请求方法,协议的版本    GET / HTTP/1.1
$status    响应状态码    200
$body_bytes_sent    给客户端发送的文件主体内容字节    0
$http_referer    可以记录用户是从哪个链接访问过来的    -
$http_user_agent    用户所使用的代理(一般为浏览器)    Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
$http_x_forwarded_for    可以记录客户端IP和所有经过的代理服务器的IP    10.1.9.98
日积月累下,日志文件会越来越大,日志文件太大严重影响服务器效率,所以需要定时对日志文件进行切割。

由于这里是演示,所以切割方式是按分钟来切割,正常生产上使用一般是按天来进行分割:

#!/bin/bash
#日志文件存放目录
LOGS_PATH=/usr/local/nginx/logs
#备份文件名称
YESTERDAY=$(date -d "yesterday" +%Y%m%d%H%M)
#重命名日志文件
mv ${LOGS_PATH}/access.log ${LOGS_PATH}/access_${YESTERDAY}.log
mv ${LOGS_PATH}/error.log ${LOGS_PATH}/error_${YESTERDAY}.log
## 向 Nginx 主进程发送 USR1 信号。USR1 信号是重新打开日志文件
kill -USR1 $(cat /usr/local/nginx/logs/nginx.pid)
1
2
3
4
5
6
7
8
9
10
然后添加定时任务:

# crontab -e
*/1 * * * * /bin/bash /usr/local/nginx/logs/nginx_log.sh
1
2
获取客户端真实IP
服务器资源分配情况如下:

10.1.9.98:充当客户端
10.0.3.137:一级代理
10.0.4.105:二级代理
10.0.4.129:三级代理
10.0.4.120:服务器端,为了方便,这里使用一个nginx充当服务器端,正常情况下一般是一个web服务器,如tomcat。
各个服务初始配置如下:

10.0.3.137的配置:

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

log_format main '$remote_addr - $http_x_forwarded_for - $http_x_real_ip';

access_log  logs/access.log  main;

server {
        listen  80;

location / {
                # proxy_set_header X-Real-IP $remote_addr;
                # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_pass http://10.0.4.105;
        }
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
10.0.4.105的配置,其他配置与10.0.3.137的一致:

...
        location / {
                # proxy_set_header X-Real-IP $remote_addr;
                # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_pass http://10.0.4.129;
        }
...
1
2
3
4
5
6
7
10.0.4.129的配置,其他配置与10.0.3.137的一致:

...
        location / {
                # proxy_set_header X-Real-IP $remote_addr;
                # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_pass http://10.0.4.120;
        }
...
1
2
3
4
5
6
7
10.0.4.120的配置,其他配置与10.0.3.137的一致

...
        location / {
                root html;
                index index.html;
        }
...
1
2
3
4
5
6
下面的记录为access.log中打印的结果:

操作    10.0.3.137    10.0.4.105    10.0.4.129    10.0.4.120
10.1.9.98访问curl http://10.0.3.137    10.1.9.98 - - - -    10.0.3.137 - - - -    10.0.4.105 - - - -    10.0.4.129 - - - -
10.0.3.137开启X-Forwarded-For    10.1.9.98 - - - -    10.0.3.137 - 10.1.9.98 - -    10.0.4.105 - 10.1.9.98 - -    10.0.4.129 - 10.1.9.98 - -
10.0.4.105开启X-Forwarded-For    10.1.9.98 - - - -    10.0.3.137 - 10.1.9.98 - -    10.0.4.105 - 10.1.9.98, 10.0.3.137 - -    10.0.4.129 - 10.1.9.98, 10.0.3.137 - -
10.0.4.129开启X-Forwarded-For    10.1.9.98 - - - -    10.0.3.137 - 10.1.9.98 - -    10.0.4.105 - 10.1.9.98, 10.0.3.137 - -    10.0.4.129 - 10.1.9.98, 10.0.3.137, 10.0.4.105 - -
10.1.9.98伪造头部访问curl http://10.0.3.137 -H ‘X-Forwarded-For: 1.1.1.1’    10.1.9.98 - 1.1.1.1 - -    10.0.3.137 - 1.1.1.1, 10.1.9.98 - -    10.0.4.105 - 1.1.1.1, 10.1.9.98, 10.0.3.137 - -    10.0.4.129 - 1.1.1.1, 10.1.9.98, 10.0.3.137, 10.0.4.105 - -
10.0.3.137开启X-Real-IP    10.1.9.98 - - - -    10.0.3.137 - 10.1.9.98 - 10.1.9.98    10.0.4.105 - 10.1.9.98, 10.0.3.137 - 10.1.9.98    10.0.4.129 - 10.1.9.98, 10.0.3.137, 10.0.4.105 - 10.1.9.98
10.0.4.105开启X-Real-IP    10.1.9.98 - - - -    10.0.3.137 - 10.1.9.98 - 10.1.9.98    10.0.4.105 - 10.1.9.98, 10.0.3.137 - 10.0.3.137    10.0.4.129 - 10.1.9.98, 10.0.3.137, 10.0.4.105 - 10.0.3.137
10.0.4.129开启X-Real-IP    10.1.9.98 - - - -    10.0.3.137 - 10.1.9.98 - 10.1.9.98    10.0.4.105 - 10.1.9.98, 10.0.3.137 - 10.0.3.137    10.0.4.129 - 10.1.9.98, 10.0.3.137, 10.0.4.105 - 10.0.4.105
10.1.9.98伪造头部访问 curl http://10.0.3.137 -H ‘X-Real-IP: 8.8.8.8’    10.1.9.98 - - - 8.8.8.8    10.0.3.137 - 10.1.9.98 - 10.1.9.98    10.0.4.105 - 10.1.9.98, 10.0.3.137 - 10.0.3.137    10.0.4.129 - 10.1.9.98, 10.0.3.137, 10.0.4.105 - 10.0.4.105
总结:

X-Forwarded-For是一个追加的过程,后面的代理会把前面代理的IP追加到X-Forwarded-For尾部,用逗号进行分隔。
应用服务器(10.0.4.120)无法从X-Forwarded-For中获取到与它直连的代理服务器的IP(10.0.4.129),此时我们可以使用r e m o t e a d d r ( 远 程 i p , 表 示 直 连 的 那 台 代 理 ) 。 当 服 务 器 无 法 过 remote_addr(远程ip,表示直连的那台代理)。当服务器无法过remote 
a
​    
 ddr(远程ip,表示直连的那台代理)。当服务器无法过http_x_forwarded_for获得上级代理或者客户端的ip时(可能没有经过代理),应该使用$remote_addr。
在代理过程中至少有一个代理设置了X-Forwarded-For,否则后面的代理或者应用服务器无法获得相关信息。
X-Forwarded-For中虽然包含了真实的客户端IP,一般是第一个IP,但是如果客户端伪造了请求头,那么真实的客户端IP就不是第一个了。
HTTP中header里面的X-Real-IP只是一个变量,后面的设置会覆盖前面的设置,所以只需要在第一个代理服务器上设置proxy_set_header X-Real-IP $remote_addr即可,然后在应用端直接引用$http_x_real_ip就行。
在java中,如果请求没有经过nginx代理,可以使用如下方法获取客户端的真实IP:

# 类似nginx中的$remote_addr
request.getRemoteHost();
1
2
如果请求经过了nginx代理,可以从请求头中获取(前提是必须正确配置nginx才能获取到):

request.getHeader("x-real-ip");
1
如果是用的其他Apache,Squid等反向代理软件,同样是从请求头中获取真实IP,只是属性名不一样而已。
————————————————
版权声明:本文为CSDN博主「morris131」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u022812849/article/details/108991869

(0)

相关推荐

  • 基于nginx反向代理获取用户真实Ip地址详解

    目录 引言 1.修改Nginx配置: 2.java获取客户端Ip 附:一个ip工具类 总结 引言 nginx做反向代理时,默认的配置后端获取到的Ip地址都来自于nginx,用request.getRemoteAddr();获取到的是nginx的ip地址,而不是用户的真实ip. 1.修改Nginx配置: server { listen 80; server_name jenkins.local.com; location / { proxy_set_header Host $host; proxy

  • 基于Nginx 反向代理获取真实IP的问题详解

    一.前言 前文Nginx 解决WebApi跨域二次请求以及Vue单页面问题 当中虽然解决了跨域问题带来的二次请求,但也产生了一个新的问题,就是如果需要获取用户IP的时候,获取的IP地址总是本机地址. 二.原因 由于Nginx反向代理后,在应用中取得的IP都是反向代理服务器的IP,取得的域名也是反向代理配置的Url的域名. 三.解决方案 解决该问题,需要在Nginx反向代理配置中添加一些配置信息,目的将客户端的真实IP和域名传递到应用程序中.同时,也要修改获取IP地址的方法. 但是需要注意的是,通

  • 让iis记录nginx反向代理的真实ip

    一.设置X-Forwarded-For段 nginx配置示例: 复制代码 代码如下: server{   location   {      ...     proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;     ...   }} 二.在iis站点上安装isapi filter 在f5的开发论坛上找到的,按开发者的话说,是为了解决iis放在f5后记录不到用户ip的问题,管他前端是f5还是nginx还是squid还是h

  • 基于java配置nginx获取真实IP代码实例

    1.java代码 /** 获取客户端IP */ public static final String getClientIp(HttpServletRequest request) { String ip = request.getHeader("X-Forwarded-For"); if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)|| "127.0.0.1".equals

  • 项目中Nginx多级代理是如何获取客户端的真实IP地址

    多级代理中获取客户端真实IP日志的格式nginx中常用日志格式配置如下: log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '                  '$status $body_bytes_sent "$http_referer" '                  '"$http_user_agent" "$http_x_fo

  • Nginx反向代理后无法获取客户端真实IP地址

    目录 1.原始配置文件如下 2.配置转发后 当我们使用 Nginx 代理转发服务后,会发现我们无法获取客户端的真实IP地址,从而无法获取客户端的地理位置等信息. 1.原始配置文件如下 worker_processes  1; events {     worker_connections  1024; } http {     include       mime.types;     default_type  application/octet-stream;     sendfile  

  • php中获取远程客户端的真实ip地址的方法

    (1).REMOTE_ADDR:浏览当前页面的用户计算机的ip地址 (2).HTTP_X_FORWARDED_FOR: 浏览当前页面的用户计算机的网关 (3).HTTP_CLIENT_IP:客户端的ip 在PHP 中使用 $_SERVER["REMOTE_ADDR"] 来取得客户端的 IP 地址,但如果客户端是使用代理服务器来访问,那取到的就是代理服务器的 IP 地址,而不是真正的客户端 IP 地址.要想透过代理服务器取得客户端的真实 IP 地址,就要使用 $_SERVER["

  • php 获取客户端的真实ip

    复制代码 代码如下: function GetIP(){ if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown")) $ip = getenv("HTTP_CLIENT_IP"); else if (getenv("HTTP_X_FORWARDED_FOR") && strc

  • php获取本机真实IP地址实例代码

    本文实例为大家分享了php获取本机真实IP地址实例代码,供大家参考. 主要是获取操作系统为win2000/xp.win7的本机IP真实地址,和获取操作系统为linux类型的本机IP真实地址,具体内容如下 function getLocalIP() { $preg = "/\A((([0-9]?[0-9])|(1[0-9]{2})|(2[0-4][0-9])|(25[0-5]))\.){3}(([0-9]?[0-9])|(1[0-9]{2})|(2[0-4][0-9])|(25[0-5]))\Z/

  • js获取客户端网卡的IP地址、MAC地址

    复制代码 代码如下: <html> <head> <title></title> </head> <body> <object classid="CLSID:76A64158-CB41-11D1-8B02-00600806D9B6" id="locator" style="display:none;visibility:hidden"></object>

  • Java中使用HttpRequest获取用户真实IP地址

    在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid,nginx等反向代理软件就不能获取到客户端的真实IP地址了. 如果使用了反向代理软件,将http://192.168.1.110:2046/ 的URL反向代理为 http://www.jb51.net / 的URL时,用request.getRemoteAddr()方法获取的IP地址是:127.0.0.1 或 192.168.1.110

  • JSP 获取真实IP地址的代码

    但是在通过了 Apache,Squid等反向代理软件就不能获取到客户端的真实IP地址了.如果使用了反向代理软件,用 request.getRemoteAddr()方法获取的IP地址是:127.0.0.1或 192.168.1.110,而并不是客户端的真实IP. 经过代理以后,由于在客户端和服务之间增加了中间层,因此服务器无法直接拿到客户端的 IP,服务器端应用也无法直接通过转发请求的地址返回给客户端.但是在转发请求的HTTP头信息中,增加了X-FORWARDED-FOR信息.用以跟踪原有的客户端

  • JSP如何获取客户端真实IP地址

    在JSP中,获取客户端IP的方法为:request.getRemoteAddr().这种方法在大部分情况下都是有效的,但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实IP地址了. 如果使用了反向代理软件,将http://192.168.1.110:3306/ 的URL反向代理为http://www.8888.com/ 的URL时,用request.getRemoteAddr()方法获取的IP地址是:127.0.0.1 或 192.168.1.110,而并不是客户端的真实

  • PHP获取客户端真实IP地址的5种情况分析和实现代码

    在PHP获取客户端IP中常使用 $_SERVER["REMOTE_ADDR"] . (1) 但如果客户端是使用代理服务器来访问,那取到的是代理服务器的 IP 地址,而不是真正的客户端 IP 地址.要想透过代理服务器取得客户端的真实 IP 地址,就要使用 $_SERVER["HTTP_X_FORWARDED_FOR"] 来读取. (2) 但只有客户端使用"透明代理"的情况下,$_SERVER["HTTP_X_FORWARDED_FOR&q

随机推荐