NGINX limit_except规则不生效问题技术求助
问题分析
你的配置预期是:所有IP可通过GET方法访问API,仅10.250.11.16/32、10.250.20.137/32两个IP能使用非GET方法(如POST/PUT/DELETE)。当前GET方法正常,但非GET方法的限制规则未生效,可从以下几点排查:
排查步骤与解决方案
1. 确认配置已正确重载
NGINX修改配置后必须重载才会生效,执行以下命令:
# 检查配置语法是否正确 nginx -t # 重载配置 nginx -s reload
如果语法检查报错,先修复配置错误再重载。
2. 验证非GET方法的实际请求结果
你提到GET方法正常是符合预期的(limit_except GET默认允许所有IP使用GET),需测试非GET方法的请求是否真的未被限制:
用非允许IP(如10.250.11.12)执行:
curl -v -X POST http://10.250.11.16:20004
如果返回200而非403,说明规则确实未生效;如果返回403,则规则已正常工作。
3. 检查api_error.conf中的冲突规则
你在server块中引入了/etc/nginx/api_conf.d/api_error.conf,需检查该文件内是否包含allow all或其他访问控制规则。如果存在allow all,会覆盖limit_except中的限制规则,导致所有IP都能使用非GET方法。
若该文件中有冲突规则,需删除或修改对应的访问控制语句。
4. 移除多余的satisfy all指令
satisfy all通常用于同时需要IP限制和身份认证的场景,当仅使用allow/deny规则时,该指令是多余的,且可能与limit_except的规则逻辑产生冲突。直接删除server块中的satisfy all语句,再重载配置测试。
5. 查看debug日志定位规则匹配情况
你的配置已开启debug级别的错误日志,可查看/var/log/nginx/debug.log,搜索请求相关的日志条目,看是否有类似以下内容:
access forbidden by rule:说明规则已触发,拒绝了请求access allowed:说明请求被允许,需检查规则匹配顺序
通过日志可明确NGINX是否正确识别了请求方法和客户端IP,并应用对应的限制规则。
修正后的参考配置
若排查后确认是satisfy all或配置未重载导致的问题,修正后的配置如下:
# NGINX IP Is 10.250.11.16 log_format 20004 '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" ' '"$bytes_sent" "$request_length" "$request_time" ' '"$gzip_ratio" $server_protocol '; server { listen 20004; status_zone server_APIAccess_MethodDeny_NGINXapi_20004; include /etc/nginx/api_conf.d/api_error.conf; error_page 404 = @400; # Invalid paths are treated as bad requests proxy_intercept_errors on; # Do not send backend errors to the client default_type application/json; # If no content-type then assume JSON location / { limit_except GET { allow 10.250.11.16/32; allow 10.250.20.137/32; deny all; } add_header X-IP "$remote_addr" always; # Tested Header add_header X-Method "$request" always; # Tested Header access_log /var/log/nginx/access.log 20004; error_log /var/log/nginx/debug.log debug; proxy_pass http://10.250.11.11/api/7/nginx; } }
内容的提问来源于stack exchange,提问作者Timo

