代理后端的 Nginx 限制真实客户端IP访问问题

一、背景–当前问题

1、正常情况,nginx 限制ip访问方式:

# nginx http\server 块中配置
allow 192.168.6.0/16;
# allow all;
deny 1.2.3.4/32;
# deny all;

2、当nginx经过前端 elb(aws负载均衡)、cdn等代理后,来源IP总是elb、cdn等代理 IP地址

当 nginx处于前端负载均衡、cdn等代理后面,来源IP总是代理IP,这样就无法如上对来源IP进行限制访问。

如这里: AWS ELB 后端获取真实客户端IP地址配置,可以获取到来源IP地址,不过只是显示看的,来源IP仍是elb、cdn等IP。

二、 解决方案

既然已经拿到用户真实 IP 地址了,稍加配置,就可以了。

1、在 Nginx 的 http 模块内加入如下配置:

# 获取用户真实IP,并赋值给变量$clientRealIP
map $http_x_forwarded_for  $clientRealIp {
        ""      $remote_addr;
        ~^(?P<firstAddr>[0-9\.]+),?.*$  $firstAddr;
}

那么,$clientRealIP 就是用户真实 IP 了,其实就是匹配了 $http_x_forwarded_for 的第一个值,具体原理:

其实,当一个 CDN 或者透明代理服务器把用户的请求转到后面服务器的时候,这个 CDN 服务器会在 Http 的头中加入一个记录
X-Forwarded-For : 用户 IP, 代理服务器 IP
如果中间经历了不止一个代理服务器,这个记录会是这样
X-Forwarded-For : 用户 IP, 代理服务器 1-IP, 代理服务器 2-IP, 代理服务器 3-IP, ….
可以看到经过好多层代理之后, 用户的真实 IP 在第一个位置, 后面会跟一串中间代理服务器的 IP 地址,从这里取到用户真实的 IP 地址,针对这个 IP 地址做限制就可以了。

而且代码中还配合使用了$remote_addr,因此$clientRealIP 还能兼容上文中第①种直接访问模式,不像 $http_x_forwarded_for 在直接访问模式中将会是空值!

所以,$clientRealIP 还能配置到 Nginx 日志格式中,替代传统的 $remote_addr 使用,推荐!

2、通过对 $clientRealIP 这个变量的判断,实现限制访问

nginx server 块中

#如果真实IP为 121.42.0.18、121.42.0.19,那么返回403
if ($clientRealIp ~* "121.42.0.18|121.42.0.19") {
        #如果你的nginx安装了echo模块,还能如下输出语言,狠狠的发泄你的不满(但不兼容返回403,试试200吧)!
        #add_header Content-Type text/plain;
        #echo "son of a bitch,you mother fucker,go fuck yourself!";
        return 403;
        break;
}

把这个保存为 deny_ip.conf ,上传到 Nginx 的 conf 文件夹,然后在要生效的网站 server 模块中引入这个配置文件,并 Reload 重载 Nginx 即可生效:

#禁止某些用户访问
include deny_ip.conf;

参考地址:https://zhangge.net/5096.html

猜你喜欢

转载自blog.csdn.net/fgf00/article/details/82260249