NGINX根据用户真实IP限源
Posted 周六happy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NGINX根据用户真实IP限源相关的知识,希望对你有一定的参考价值。
一、背景介绍
1、正常情况,nginx 限制ip访问方式:(根据remote_addr限制)
# nginx http\\server 块中配置
allow 192.168.6.0/16;
# allow all;
deny 1.2.3.4/32;
# deny all;
2、当经过waf或者cdn等代理后(remote_addr总是waf或者cdn等上一步代理地址)
3、确认上层代理是否将用户IP传递到http_x_forwarded_for中
4、一般http_x_forwarded_for中第一个地址为用户IP,为了避免被人篡改,暂不采取直接拿第一个地址作为用户真实IP
二、基础知识介绍
1、remote_addr
HTTP协议没有IP的概念,Remote Address来自于TCP连接,表示与服务端建立TCP连接的设备IP,因此,Remote Address无法伪造。注意,这里的客户端指的是直接请求Nginx的客户端,非间接请求的客户端。
用户客户端–发送请求->Nginx1 --转发请求–>Nginx2->后端服务器
默认情况下,针对Nginx1而言,remote_addr为用户客户端IP,对Nginx2而言,$remote_addr则为Nginx1的IP。
2、X-Real-IP
HTTP代理用于表示与它产生TCP连接的设备IP,可能是其他代理,也可能是真正的请求端。
用途:当本机 Nginx 处于反向代理后端时可以获取到用户的真实IP地址。
realip 功能介绍
使用:realip 功能需要 Nginx 添加 ngx_http_realip_module 模块,默认情况下是不被编译,如果需要添加,请在编译时添加 --with-http_realip_module 选项开启它。
realip 作用域
set_real_ip_from、real_ip_header 和 real_ip_recursive 都可以用于 http、 server、location 区域配置。
realip 部分参数解释
set_real_ip_from:设置反向代理服务器,即信任服务器IP
real_ip_header X-Forwarded-For:用户真实IP存在X-Forwarded-For请求头中
real_ip_recursive:
off:会将real_ip_header指定的HTTP头中的最后一个IP作为真实IP
on:会将real_ip_header指定的HTTP头中的最后一个不是信任服务器的IP当成真实IP
3、X-Forwarded-For
Nginx追加上去的,但前面部分来源于nginx收到的请求头,这部分内容不是很可信。符合IP格式的才可以使用,否则容易引发XSS或者SQL注入漏洞。
每次经过proxy转发都会有记录,格式就是 client1,proxy1,proxy2,以逗号隔开各个地址,由于它是非rfc标准,所以默认是没有的,需要强制添加。
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
追加一个X-Forwarded-For的值,实际上当你搭建两台nginx在不同的ip上,并且都使用了这段配置,那你会发现在web服务器端通过request.getAttribute(“X-Forwarded-For”)获得的将会是客户端ip和第一台nginx的ip。
4、deny机制
Nginx的deny和allow指令是由ngx_http_access_module模块提供,Nginx安装默认内置了该模块。
语法
语法:allow/deny address | CIDR | unix: | all
它表示,允许/拒绝某个ip或者一个ip段访问.如果指定unix:,那将允许socket的访问。
注意:unix在1.5.1中新加入的功能。
在nginx中,allow和deny的规则是按顺序执行的。
allow 指令
1、允许哪些 IP 访问,all 表示允许所有;
2、作用域 http / server / location / limit_except ;
deny 指令
1、禁止哪些 IP 访问,all 表示禁止所有;
2、作用域 http / server / location / limit_except ;
运行机制
根据remote_addr参数限制允许还是拒绝
三、当前场景问题
1、real_ip获取用户真实IP
经过waf代理,remote_addr 为waf出口地址
- 开启real_ip,取X-Forwarded-For中最后一个ip作为real_ip
- 设置信任ip(中间代理服务器出口地址,本场景为waf出口地址),设置后real_ip在取值时候会过滤掉 X-Forwarded-For中信任的ip
- 本场景作用域为http
set_real_ip_from 2.2.2.2;
set_real_ip_from 2.2.2.3;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
2、赋值给remote_addr,使得deny生效
本场景此处作用域为location
proxy_set_header X-Real-IP $remote_addr;
3、如何限制用户访问
本场景此处作用域为location,写在上一步之后
include whitelist.conf;
其中whitelist.conf路径为nginx.conf同级目录中,文件中写入内容为:
allow 112.17.28.67 ;
allow 112.17.79.152/29;
deny all;
四、测试
1、检查配置文件
nginx -t
2、重新加载nginx
nginx -s reload
3、测试白名单中有的地址能否访问
4、测试白名单中没有的地址能否访问
五、注意
一定要检查配置文件地址跟改动的配置文件地址是否一致,否则会导致更改失效
获取用户真实IP:(模拟:客户端--F5--nginx--tomcat 后端获取用户真实IP)
模拟:客户端--F5--nginx--tomcat 后端获取用户真实IP
192.168.109.137 :nginx01(充当第一层代理==F5)
192.168.109.138 :nginx02(二层代理,业务转发)
192.168.109.139 :tomcat (后端业务层)
192.168.109.1 :客户端IP
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
一。安装好访问如图:
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
二。配置代理查看效果,以及日志
1。 192.168.109.137 将所有请求代理到二级代理192.168.109.138去(proxy_pass http://192.168.109.138;)效果如下:
192.168.109.137:tail -f access.log
192.168.109.138:tail -f access.log
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
三。设置日志打印格式,以及ip
1.一级代理192.168.109.137 nginx(F5)设置:
以下分别解释并测试效果:
1.proxy_set_header Host $host; 或者 proxy_set_header Host $host:$proxy_port; ($host代表转发服务器,$proxy_port代表137转发服务器请求后端服务器的端口,也就是80)
$host :$proxy_port指的的就是转发服务器【192.168.109.137 nginx(F5)】的servername 和监听端口,我这里配置的是listen 80;server_name 192.168.109.137;
在192.168.109.138的nginx日志打印中加入$http_host ‘ log_format main ‘....$http_host ‘
测试:
2.proxy_set_header X-Real-IP $remote_addr;
将$remote_addr的值放进变量X-Real-IP中,此变量名可变,$remote_addr的值为客户端的ip
一级代理nginx(F5)的日志配置:
log_format main ‘$remote_addr - $remote_user [$time_local] "$request" $http_host ‘
‘$status $body_bytes_sent "$http_referer" ‘
‘"$http_user_agent" "$http_x_forwarded_for"‘;
二级代理nginx02的日志配置如下:(两者区别在于"$http_x_real_ip",添加了这个变量的值)
log_format main ‘$remote_addr "$http_x_real_ip" - $remote_user [$time_local] "$request" "$http_host" ‘
‘$status $body_bytes_sent "$http_referer" ‘
‘"$http_user_agent" "$http_x_forwarded_for"‘;
继续测试:
3.proxy_set_header X-Forwarded-For $remote_addr; 与 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
两者的区别:
在只有一个代理服务器的转发的情况下,两者的效果貌似差不多,都可以真实的显示出客户端原始ip
但是区别在于:
$proxy_add_x_forwarded_for变量包含客户端请求头中的"X-Forwarded-For",与$remote_addr两部分,他们之间用逗号分开。
继续测试:
一级代理nginx(F5)日志配置:
log_format main ‘$remote_addr - $remote_user [$time_local] "$request" $http_host ‘
‘$status $body_bytes_sent "$http_referer" ‘
‘"$http_user_agent" "$http_x_forwarded_for"‘;
二级代理nginx02日志配置:
log_format main ‘$remote_addr "$http_x_real_ip" - $remote_user [$time_local] "$request" "$http_host" ‘
‘$status $body_bytes_sent "$http_referer" ‘
‘"$http_user_agent" "$http_x_forwarded_for"‘;
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2.二级代理192.168.109.137 nginx02设置:
set_real_ip_from 是指接受从哪个信任前代理处获得真实用户ip
real_ip_header 是指从接收到报文的哪个http首部去获取前代理传送的用户ip
real_ip_recursive on; #递归的去除所配置中的可信IP。排除set_real_ip_from里面出现的IP。如果出现了未出现这些IP段的IP,那么这个IP将被认为是用户的IP
注意:后端tomcat 一般是通过X-FORWARDED-FOR拿取客户端真实IP
tomcat日志打印配置:
vim server.xml
pattern="%{X-FORWARDED-FOR}i %h %l %u %t "%r" %s %b" />
pattern参数详解参考:http://sofar.blog.51cto.com/353572/1712069/
以上是关于NGINX根据用户真实IP限源的主要内容,如果未能解决你的问题,请参考以下文章