麦都-平台开发组

Tengine后端代理机,获取用户真实IP做并发访问限制的方法

写作时间:2018-05-08

一、普通配置

## 用户的 IP 地址 $binary_remote_addr 作为 Key,每个 IP 地址最多有 10 个并发连接
## 你想开 几千个连接 刷死我? 超过10个连接,直接返回错误给你,根本不处理你的请求了

limit_req_zone $binary_remote_addr zone=one:6m rate=10r/s;

limit_req_zone $binary_remote_addr $uri zone=two:6m rate=10r/s;

limit_req_zone $binary_remote_addr $request_uri zone=thre:6m rate=10r/s;

## 具体服务器配置

server {

#最多 5 个排队, 由于每秒处理 10 个请求 + 5个排队,你一秒最多发送 15 个请求过来

limit_req zone=one burst=5 nodelay;

limit_req zone=two burst=5 forbid_action=@test1 nodelay;

location @test1 {

rewrite ^ /404.html;

}

}

这样一个最简单的服务器安全限制访问就完成了

二、后端服务器

网站的访问模式就变为:

用户浏览器 → 负载节点 → 网站源服务器

可以看到,我们的网站中间经历了好几层的透明加速和安全过滤, 这种情况下,我们就不能用上面的“普通配置”。因为普通配置中基于【源 IP 的限制】的结果就是,我们把【 负载 节点】给限制了,因为这里“源 IP”地址不再是真实用户的 IP,而是负载节点的 IP 地址。

我们需要限制的是最前面的真实用户,而不是中间为我们做加速的加速服务器。

其实,当一个 CDN 或者透明代理服务器把用户的请求转到后面服务器的时候,这个 CDN 服务器会在 Http 的头中加入一个记录

X-Forwarded-For :  用户 IP, 代理服务器 IP

如果中间经历了不止一个代理服务器,这个记录会是这样

X-Forwarded-For :  用户 IP, 代理服务器 1-IP, 代理服务器 2-IP, 代理服务器 3-IP, ….

可以看到经过好多层代理之后, 用户的真实 IP 在第一个位置, 后面会跟一串中间代理服务器的 IP 地址,从这里取到用户真实的 IP 地址,针对这个 IP 地址做限制就可以了。

那么针对负载 模式下的访问限制配置就应该这样写:

## 这里取得原始用户的IP地址
map $http_x_forwarded_for  $clientRealIp {
	""	$remote_addr;
	~^(?P<firstAddr>[0-9\.]+),?.*$	$firstAddr;
}

limit_req_zone $clientRealIp zone=one:6m rate=10r/s;

limit_req_zone $clientRealIp $uri zone=two:6m rate=10r/s;

limit_req_zone $clientRealIp $request_uri zone=thre:6m rate=10r/s;

server{

limit_req zone=one burst=40 nodelay;

limit_req zone=two burst=40 forbid_action=@test1 nodelay;

location @test1 {

rewrite ^ /404.html;

}

}

参考地址:http://tengine.taobao.org/document_cn/http_limit_req_cn.html