nginx网关中使用realip模块
最近在项目中,遇到了关于nginx中配置白名单的问题。当中踩了一点坑,进行一个小结。
需求的背景是:让某个url只允许某些网段可访问
首先,前端请求在系统中的转发过程是:到集群代理服务器、然后再到云网关(如xlb)、接着到nginx网关、最后到前端的项目服务。
查阅相关资料,查找nginx相关知识。在对应的配置文件中,找到某个url(如: aaa)的配置, 然后进行配置。
location ~ /(aaa|bbb ) {
real_ip_header X-Forwarded-For;
real_ip_recursive on;
allow xx.xxx.xx.xxx;
allow xxx.xxx.xx.xxx;
allow 192.168.0.0/16;
allow 10.0.0.0/8;
allow 172.xx.0.0/12;
deny all;
}
这里,location的匹配规则:
= 表示精准匹配
~表示区分大小写的正则匹配 以aaa, bbb结尾
~*表示不区分大小写的正则匹配 以aaa, bbb结尾
^~表示以某字符开头,只匹配路径 如请求为/static/20%/aa可以被规则 ^~ /static//aa匹配到 以xxx开头
/ 任何请求都会匹配
通过测试发现,使用外网访问url,仍然可访问。在容器中进行验证可到的结果反而是已生效。通过容器中的日志查询,发现了外网访问先到xlb, 接着再到nginx网关。到达xlb时访问的ip已不是外网ip,真实IP没有被识别。会被ip命中从而可以访问。
通过了解相关知识,需要增加配置set_real_ip_from, 于是更改后的配置变为
location ~ /(aaa|bbb ) {
xx1.xx.xx.0 //代理服务器IP或者网段1
et_real_ip_from xx2.xx.xx.xx //代理服务器IP或者网段2
et_real_ip_from xx3.xx.xx.xx //代理服务器IP或者网段3
real_ip_header X-Forwarded-For;
on;
allow xx.xxx.xx.xxx; //允许访问的IP或网段
allow xxx.xxx.xx.xxx;
allow 192.168.0.0/16;
allow 10.0.0.0/8;
allow 172.xx.0.0/12;
deny all;
}
其中,set_rel_ip_from: 表示来自代理服务器的IP,不是用户的真实IP
real_ip_header: 表示从header中的哪个属性检索出所要的IP
例如:真实服务器获取的IP串如下
xx4.xx.xx.xx xx3.xx.xx.xx xx2.xx.xx.xx xx1.xx.xx.0
当real_ip_recursive: on, xx3.xx.xx.xx xx2.xx.xx.xx xx1.xx.xx.0 都在set_rel_ip_from列表中,递归到xx4.xx.xx.xx时,会认为这个IP是用户IP。意思是将IP串中最后一个不是set_real_ip_from中的IP命中;
当real_ip_recursive: off 时,会将最后一个IP作为用户IP,即xx3.xx.xx.xx,实质上这是代理服务器3的IP.
在这次配置上线中,除了需要nginx realip的相关知识储备外,还需要了解从浏览器输入url 到请求到达服务器经历的过程。当然,如果是购买了云厂商的服务(如华为云、AWS等),可进行负载均衡配置,不需在网关层进行处理,具体需要结合项目的结构。
想更详尽的了解nginx realip的知识,可以参考http://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from