CC是常见的网络攻击方法,通过有限的IP去不断请求服务器导致服务器资源耗尽宕机,因此利用NGINX的限频可以在一定程度上降低CC攻击的危害。主要用到的有HttpLimitReqModule和HttpLimitZoneModule,两者都可以基于IP来限制访问频率,不过前者限制的是HTTP请求数、后者限制的是TCP并发连接数。
注意
由于使用的是$binary_remote_addr,即IP地址的二进制格式,判断的标准为与NGINX实际建连的IP,因此这里的配置不适合前端有反向代理或者CDN的情形。
HttpLimitReqModule使用limit_req_zone和limit_req指令配合达到限制的目的。一旦一段时间内单个IP的HTTP请求超过指定数量,就会返回503错误(为了方便通常可以改为429错误,即429 Too Many Requests)。
HttpLimitConnModule用来限制单个IP的并发连接数,使用limit_zone和limit_conn指令。
HttpLimitReqModule 限制某一段时间内同一IP访问数
http{
...
# 定义一个名为httplimit的limit_req_zone用来存储session,大小是10M内存
# 以 $binary_remote_addr 即IP地址的二进制格式为key,限制平均每秒的请求为30个(单位r/s可以改为r/m,即每分钟多少次)
# 1M能存储16000个状态,rete的值必须为整数
limit_req_zone $binary_remote_addr zone=httplimit:10m rate=30r/s;
# 超出时返回429错误(默认返回503)
limit_req_status 429;
...
server{
...
# 限制每IP每秒不超过30个请求,漏桶数burst为10
# brust的意思就是超出30个请求的情况下,如果没有设置nodely,后续的10个请求会放进burst里等待,超出rate + burst的直接返回429错误
# nodelay,如果设置该选项,则在规定的时间内直接处理rate+burst即40个请求,相当于限制每IP每秒不超过40个请求,超出rate + burst的直接返回429错误
limit_req zone=httplimit burst=30 nodelay
...
}
...
}
HttpLimitZoneModule 限制并发连接数
该功能限制的是TCP连接数
http{
...
# 定义一个名为tcplimit的limit_zone,大小10M内存来存储session
# 以 $binary_remote_addr 为key
# nginx 1.18以后用limit_conn_zone替换了limit_conn
limit_conn_zone $binary_remote_addr zone=tcplimit:10m;
# 超出时返回429错误(默认返回503)
limit_conn_status 429;
...
server{
...
limit_conn tcplimit 40; # 连接数限制
limit_rate 500K; # 单连接带宽限制
...
}
...
}