有时候服务器会遭到大流量的恶意访问,这种攻击最直接的影响就是导致服务器持续高压,严重影响正常访问,导致这种情况的原因有很多,对于一些低配置的服务器可能只需要一次简单的恶意压测就可以导致服务器502.对于这种情况,我们可以考虑对相同IP的并发连接数和请求频率进行限制,nginx本身自带了两个模块可以作为解决方案,即ngx_http_limit_conn_module和ngx_http_limit_req_module.
ngx_http_limit_conn_module
简介:ngx_http_limit_conn_module是一个可以根据指定key来限制连接数的模块,尤其用于根据单个IP限制连接数.
语法:limit_conn_zone key zone=name:size;
上下文:http(即nginx配置的http作用域)
说明:开辟一个名为name,大小为size的共享内存区域,用于存储一系列key(s)的状态,特别是包含各个key的连接数,其中key可以是变量、文本或二者的组合(nginx 1.7.6之前只可以包含一个变量),另外1MB共享内存可以存储3.2万个32-byte状态(在32位平台中存储状态占用32bytes)或1.6万个64-byte(64位平台),当共享内存空间不足时,之后的请求会导致服务器返回503(Service Temporarily Unavailable) 错误.
语法:limit_conn zone number;
上下文:http ,server,location
说明:设置共享内存区域zone,使zone指定的key的连接数不大于number个,当超过这个number值时服务器会返回503(Service Temporarily Unavailable) 错误.
例子:设定一个名为addr的10MB共享内存,以客户端ip作为键,限制每个客户端ip最大并发连接数为5
http{ ... # $binary_remote_addr是客户端ip地址,它和$remote_addr的区别在于它是固定4字节长度 limit_conn_zone $binary_remote_addr zone=addr:10m; server { ... location ~ \.php$ { limit_conn addr 5; } ... } ... }
ngx_http_limit_req_module
简介:ngx_http_limit_req_module是一个可以根据给定的key来限制请求处理频率的模块.特别的,根据客户端IP来限制单个IP的请求频率,这种限制是基于“漏桶算法”来实现(每秒处理固定请求,多出的请求延迟处理).
语法:limit_req_zone key zone=name:size rate=rate;
上下文:http
说明:开辟一个名为name,大小为size的共享内存区域,用于存储一系列key(s)的状态,特别是包含各个key的超出的请求数,其中key可以是变量、文本或二者的组合(nginx 1.7.6之前只可以包含一个变量),另外1MB共享内存可以存储3.2万个32-byte状态(在32位平台中存储状态占用32bytes)或1.6万个64-byte(64位平台),当共享内存空间不足时,之后的请求会导致服务器返回503(Service Temporarily Unavailable) 错误.请求的key为空时不作计算.
语法:limit_req zone=name [burst=number] [nodelay];
上下文:http ,server,location
说明:设置指定的共享内存区域和超过频率限制的最大请求数,当请求频率大于rate时,超出的请求会被延迟,因而所有请求都是严格按照rate的频率来执行的,当延迟的请求大于burst时将会产生503(Service Temporarily Unavailable) 错误,如果不希望超出频率的请求被延迟执行,可以设置nodelay属性.
例子:限定每个IP的请求频率不超过每秒2次,同时允许超过频率限制的请求不多于15个
http { ... limit_req_zone $binary_remote_addr zone=reqlimit:10m rate=2r/s; ... server { ... location ~ \.php$ { limit_req zone=reqlimit burst=15; ... } ... } ... }
提示:页面的静态资源往往需要较多的请求,为了防止阻塞用户请求,应该根据location作用域对js、css、jpg等静态资源不作限制.另外,如果前端做了LVS,那么会有大量的相同IP请求,又或者不希望限制搜索引擎的蜘蛛等,这些情况可以通过白名单IP过滤,参考ngx_http_geo_module模块的geo指令