如何针对整个子网而非单个IP配置Nginx请求速率限制?
解决Nginx按IP子网(/24)进行速率限制的方案
没问题,针对这种客户端通过轮换同子网IP规避单IP限速的情况,我们可以通过提取客户端IP的子网段来替换原有的单IP标识,从而实现对整个/24网段的速率限制。下面是具体的实现步骤:
1. 定义子网标识变量
首先在Nginx配置的http块中,使用map模块将客户端IP转换为对应的/24子网段。这样就能把同一个/24内的所有IP映射到同一个标识上:
map $remote_addr $client_subnet { # 匹配IPv4地址,提取前三个段,拼接为xxx.xxx.xxx.0/24作为子网标识 ~^(?P<ip_prefix>\d+\.\d+\.\d+)\. $ip_prefix.0/24; # 处理非IPv4的情况(比如IPv6或异常IP),默认保留原IP default $remote_addr; }
如果你的服务需要支持IPv6,还可以添加IPv6 /64网段的匹配规则(大部分IPv6分配都是按/64段进行的):
map $remote_addr $client_subnet { # IPv4 /24 ~^(?P<ip_prefix>\d+\.\d+\.\d+)\. $ip_prefix.0/24; # IPv6 /64:提取前64位(以冒号分隔的前4段) ~^(?P<ipv6_prefix>[0-9a-fA-F:.]{1,47}): $ipv6_prefix::/64; default $remote_addr; }
2. 修改速率限制区域配置
接下来把原来的limit_req_zone中的$binary_remote_addr替换为我们刚定义的$client_subnet:
limit_req_zone $client_subnet zone=leash:10m rate=18r/s;
⚠️ 注意:由于$client_subnet是字符串格式(比二进制的$binary_remote_addr占用更多空间),如果你的服务有大量不同的子网段访问,可能需要适当调大zone的大小(比如从10m改成20m),避免因空间不足导致限速失效。
3. 验证配置效果
修改完成后,重启Nginx服务使配置生效:
nginx -s reload
然后可以用同一/24网段内的不同IP发起请求测试,比如用两台同子网的机器或者修改本地IP,多次请求后应该会触发速率限制,说明配置生效。
额外注意事项
- 如果你的Nginx部署在反向代理(如CDN、负载均衡)之后,
$remote_addr会是代理服务器的IP,这时候需要改用$http_x_forwarded_for来获取真实客户端IP,但一定要在配置中限制可信代理的IP,防止客户端伪造X-Forwarded-For头规避限制。 - 可以根据实际需求调整子网掩码(比如/16或/32),只需要修改
map中的正则和拼接规则即可。
内容的提问来源于stack exchange,提问作者Istvan Prosinger
相关产品推荐
相关产品推荐

