一、背景介绍
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、测试白名单中没有的地址能否访问
五、注意
一定要检查配置文件地址跟改动的配置文件地址是否一致,否则会导致更改失效
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论