WordPress 使用 Nginx 限制每个 IP 地址访问 URL 的频率
在保护 API 接口、阻止暴力破解和预防 CC 攻击等方面,我们希望限制单个 IP 访问 URL 的频率,比如每秒只能请求一次,或每分钟访问一次等,Nginx 的 limit_req_zone
可以实现限制请求速率的需求。虫子菌将以宝塔面板 + WordPress 网站为例,详细解读 limit_req_zone 的参数配置。
1. limit_req_zone
http { #... #设置名为 cccitu 的内存区域,10 MB大小,单个 IP 限制每分钟访问 1 次 limit_req_zone $binary_remote_addr zone=cccitu:10m rate=1r/m; server { #... #对 https://www.cccitu.com/5065.html 进行访问频率限制 location =/5065.html { #如果同 IP 一分钟内发起 10 并发请求,第 1 个请求立即处理,缓存 5 个请求后每分钟处理一个,剩下的 4 个直接返回 503 错误 limit_req zone=cccitu burst=5 nodelay; } }}
如上所示,limit_req_zone 的启用只有非常简单的两行代码,将它们写在 Nginx 的配置文件中即可生效。
imit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
只能放在 http {} 内;limit_req zone=one burst=5 nodelay;
则可以根据需要放在 http {} (对服务器内所有的网站生效)、server {} (对具体的一个网站生效)或 location {} (对具体的一个网址生效)
2. 实例部署
虫子菌以使用宝塔面板部署的 WordPress 的网站为例,假设要限制对 https://www.cccitu.com/5065.html
的请求速率,每个 IP 地址,每分钟只能访问此网址 1 次。部署过程分为两部分:第一部分在 http {} 内开启 limit_req_zone 功能,第二部分在 location {} 内对具体 URL 做频率限制。
2.1 第一部分 http {}
2.1.1 代码部署:
#zone= 和 rate= 的内容,可以根据需要自行设置limit_req_zone $binary_remote_addr zone=cccitu:10m rate=1r/s;
将如上代码添加到 Nginx 配置文件的 http {} 内。
2.1.2 参数解读:
zone=cccitu:10m
:rate=1r/m
:
将 IP 地址保存在名为 cccitu 内存区域,该区域储存空间为 10 MB。区域名称可以随便设置,但要注意后面用的时候名称要一致;1m 空间大约能保存 1.6 万条 IP 地址,10m 完全够用了,空间满了新数据会覆盖旧数据。
限制访问请求频率为每分钟 1 次,可根据需要自行设置,1r/s
是 1 秒 1 次,30r/m
是 1 分钟 30 次(换算为 2 秒 1 次),需要注意时间单位只能选择 s (秒)或 m (分),最低频率限制是每分钟 1 次访问请求。
2.2 第二部分 location {}
2.2.1 代码部署:
location = /5065.html { #以下需根据实际情况修改 #教程:https://www.cccitu.com/5065.html limit_req zone=cccitu burst=5 nodelay; try_files $uri $uri/ /index.php?$args; fastcgi_pass unix:/tmp/php-cgi-73.sock; #以下固定内容,无需修改 fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name; }
将如上代码添加到 Nginx 的配置文件针对 www.cccitu.com 站点的 server {} 内。
2.2.2 参数解读:
location = /5065.html
:
= /5065.html 只对网址 www.cccitu.com/5065.html 生效,= / 只对 www.cccitu.com 生效,只保留 location 后面什么也不写则是对该网站的所有网址生效。
limit_req zone=cccitu burst=5 nodelay;
:
zone=cccitu 是存放 IP 地址的内存区域名称,要与第一部分在 http {} 中设置的名称保持,前面叫 cccitu,这里也要写 cccitu。这一行其实有 3 种写法,在此例子中我们将限制频率为 1 分钟 1 次(rate=1r/s),如果瞬间并发了 10 次请求,这 3 种写法的效果分别如下 :
#立即处理第 1 个请求,其余 9 个直接返回 503 错误limit_req zone=cccitu; #立即处理第 1 个请求,第 2-6 个请求缓存后排队 1 分钟处理 1 个,第 7-10 个请求返回 503 错误limit_req zone=cccitu burst=5; #立即处理第 1-5 个请求,第 7-10 请求返回 503 错误limit_req zone=cccitu burst=5 nodelay;
try_files $uri $uri/ /index.php?$args;
:
是 WordPress 的伪静态(宝塔面板——网站——设置——伪静态)如果你没设置伪静态或者没用 WordPress,可以删掉不写。
fastcgi_pass unix:/tmp/php-cgi.sock;
:
PHP 连接配置,有 192.168.1.25:9001
或 unix:/tmp/php8.sock
两种写法,并且不同版本的 PHP 所写内容也不同,具体怎么写,请与所使用 PHP 的 FPM 配置文件一致(宝塔面板——软件商店——所安装PHP——FPM 配置文件)
其它没提及的内容,是默认固定配置,不用专门修改。
2.3 额外补充:
location = /5065.html { #教程:https://www.cccitu.com/5065.html limit_req zone=cccitu burst=5 nodelay; try_files $uri $uri/ /index.php?$args; }
对于宝塔面板 + WordPress,如果针对的 URL 是文章/标签/分类,不是 网站首页、wp-login.php、admin-ajax.php 等,那么,http {} 保持不变,location {} 有更简单的写法,如上所示。