Nginx流量限制

Nginx流量限制可以有效防止DDOS攻击,降低服务器负载,缓解硬件和网络压力,功能依赖于limit_req模块,这个模块现版本都是默认集成的,所以不用单独编译安装。

转载资料:

关于limit_req和limit_conn的区别:https://www.cnblogs.com/zhoulujun/p/12183179.html

Nginx限制访问速率和最大并发连接数模块说明:https://www.cnblogs.com/wjoyxt/p/6128183.html

Nginx下limit_req模块burst参数超详细解析:https://blog.csdn.net/hellow__world/article/details/78658041

关于limit_req和limit_conn的区别
what is the difference between connection and request?

Nginx限流配置–limit_req和limit_conn (防范DDOS攻击)
https://www.cnblogs.com/andrew-303/p/12272099.html

connection是连接,即常说的tcp连接,通过三次握手而建立的一个完整状态机。建立一个连接,必须得要三次握手。
request是指请求,即http请求,tcp连接是有状态的,而构建在tcp之上的http却是无状态的协议
通过打开一个网页,然后通过wareshark可以看到,一个连接建立后(即三次握手后),在这个连接断开之前(即四次挥手之前),会有很多的http request,这就是他们的区别:即一个连接的生命周期中,会存在一个或者多个请求,这是为了加快效率,避免每次请求都要三次握手建立连接,现在的HTTP/1.1协议都支持这种特性,叫做keepalive。

limit_conn_zone $binanry_remote_addr zone=conn_zone:1m;

limit_conn conn_zone 1;  

这样的配配置,表明以ip为key,来限制每个ip访问lmit.html文件时候,最多只能有一个在线,否则其余的都要返回不可用。

这种情况就是一个静止状态的计数可以实现,而无关乎多长时间。

举个例子,如果你的这个连接一直不释放,即使你通过这一个连接发送出再多的request请求,只要我能够应付,那么我就帮你处理。

但是,如果你只需要处理2个请求,但是这两个请求是分别用两个连接同时发送过来的,那么,我就只能处理其中一个,另外一个就不行。这就是他的区别。

limit_req_zone $binary_remtoe_addr zone=req_zone:1m rate=1r/s; #这里需要为共享内存配置一个速率rate,

limit_conn zone=req_zone;

表明:对于每个ip来说,处理请求的速度不超过每秒1个请求。

可以看到这是个速度量(而上面的那个是数字量,速度和个数还是有直观的区别的吧。。)

是同时发送出100个请求(不管是通过100个连接还是1个连接),只要你请求到底的速度超过每秒1个,那么我就会拒绝你。

对于与 burst,推荐阅读:Nginx下limit_req模块burst参数超详细解析 https://blog.csdn.net/hellow__world/article/details/78658041

这里把其总结摘录如下:

limit_req zone=req_zone;
严格依照在limti_req_zone中配置的rate来处理请求
超过rate处理能力范围的,直接drop
表现为对收到的请求无延时

limit_req zone=req_zone burst=5;
依照在limti_req_zone中配置的rate来处理请求
同时设置了一个大小为5的缓冲队列,在缓冲队列中的请求会等待慢慢处理
超过了burst缓冲队列长度和rate处理能力的请求被直接丢弃
表现为对收到的请求有延时

limit_req zone=req_zone burst=5 nodelay;
依照在limti_req_zone中配置的rate来处理请求
同时设置了一个大小为5的缓冲队列,当请求到来时,会爆发出一个峰值处理能力,对于峰值处理数量之外的请求,直接丢弃
在完成峰值请求之后,缓冲队列不能再放入请求。如果rate=10r/m,且这段时间内没有请求再到来,则每6 s 缓冲队列就能回复一个缓冲请求的能力,直到回复到能缓冲5个请求位置。

小伙伴对这个zone估计还是有一些疑问,有疑问可以在下面评论,大家一起讨论,比如,有人可能会问,一个客服端占用5个,那么327680只能容纳65536个客服端,那么第65537个客服端就会返回503错误

limit_conn_zone
语法:

Syntax: limit_conn_zone key zone=name:size;
Default: —
Context: http
看上面的语法,limit_conn_zone只能用在http段,例如:

http {
    
    
limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
    
    
listen 80;
server_name www.tomener.com tomener.com;
location / {
    
    
root /var/www/tomener;
index index.php index.html index.htm;
limit_conn addr 5; #是限制每个IP只能发起5个连接
limit_rate 100k; #限速为 100KB/秒
}
}
}

对于关系:
key => $binary_remote_addr #二进制的IP地址
name => addr #随便取的一个名字,比如,你可以取成abc
size => 10m #空间大小,这里是10兆
一个二进制的ip地址在32位机器上占用32个字节,在64位机器上占用63个字节,那么10M可以存放多少呢,计算一下,10x1024x1024/32 = 327680,意思就是可以存放326780个ip地址(32位),64位可以存放163840个ip

1、key:键,可以说是一个规则,就是对客户端连接的一个标识,比如上面用的是IP地址,比如我们可以用$query_string,例如:/index.php?mp=138944093953,那我们就可以根据mp的值来限制连接数,更多的nginx内置变量请查看http://nginx.org/en/docs/varindex.html

2、zone:共享内存空间,作用:保存每个key对应的连接数

3、size:共享内存空间大小,如1M、10M、100K
当共享内存空间被耗尽,服务器将会对后续所有的请求返回 503 (Service Temporarily Unavailable) 错误

limit_conn_log_level指令
Syntax: limit_conn_log_level info | notice | warn | error;
Default: limit_conn_log_level error;
Context: http, server, location
说明:当达到最大限制连接数后,记录日志的等级。

limit_conn_status指令
Syntax: limit_conn_status code;
Default: limit_conn_status 503;
Context: http, server, location
说明:当超过限制后,返回的响应状态码,默认是503,现在你就知道上面为什么会返回503(Service Temporarily Unavailable)服务暂时不可用

例子:

1、同时限制ip和虚拟主机最大并发连接

http {
    
    
limit_conn_zone binaryremoteaddrzone=perip:10m;limitconnzonebinaryremoteaddrzone=perip:10m;limitconnzoneserver_name zone=perserver:10m;
server {
    
    
location / {
    
    
limit_conn perip 10;
limit_conn perserver 1000;
}
}
}

最后放一个在公司遇到的需求,有个项目是请求服务器上的一个服务接口,但是程序请求的太频繁了,导致服务这边请求过快,被第三方侦测为恶意爬取而导致了封号。按说应该修改一下程序,降低请求速率,但是恰巧开发程序的人联系不到了,那只能下策,修改咱们Nginx代理的接口这边的流量限制,从而达到降低请求频率的目的。

Nginx修改的位置只有两处
主配置文件:

vim nginx.conf
http {
    
    
    include       mime.types;
    default_type  application/octet-stream;
    limit_req_zone $binary_remote_addr zone=one:10m rate=2r/m;

虚拟服务器的配置文件:

        location  /xxx {
    
    
          limit_req zone=one burst=30 nodelay;
          proxy_pass      http://127.0.0.1:8090;
          proxy_set_header Host   $host;
          proxy_set_header X-Real-IP      $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

做好后写个验证脚本

/bin/bash
while :
do
echo 开始执行调用
curl -s -w '%{http_code}' "http://xxx.xxx.cn/xxx/xxx
echo 睡眠10秒后再次请求
sleep 10
done

跑一下,因为咱们设定的是30秒接受一次请求,缓存池是5次,也就是说跑这个脚本时是跑到第7次时出现503返回值,然后每两次503一次200的频率,就验证成功了

猜你喜欢

转载自blog.csdn.net/qq_35855396/article/details/118314934
今日推荐