Nginx代理接收含URL的查询参数时返回403 forbidden错误
问题原因
你遇到的403错误基本是Nginx自带/第三方安全模块的拦截规则导致的:
- 多数安全规则默认会把查询参数中携带的第三方URL判定为SSRF探测、恶意跳转注入等恶意行为,直接拦截返回403
- Nginx默认开启
merge_slashes指令,会把URL编码后的%2F自动解码为/,导致参数内的路径被识别为请求路径的一部分,触发路径拦截规则 - 部分自定义配置里可能写死了拦截查询参数带
http:///https://的规则,你没有注意到
解决步骤
1. 排查显式拦截规则
全局扫描Nginx配置目录,检查有没有硬编码的拦截规则:
grep -r "query_string.*http" /etc/nginx/
如果返回类似if ($query_string ~* "https?:\/\/") { return 403; }的规则,直接删除或者调整规则排除/proxy路径即可。
2. 调整路径合并配置
在你的站点server块或者/proxy专属location块中关闭斜杠自动合并:
server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name mydomain.com; # 关闭斜杠合并,避免参数内的%2F被错误解析 merge_slashes off; # 建议单独给/proxy写location配置,优先级高于全局/路径 location /proxy { proxy_pass http://localhost:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } location / { proxy_pass http://localhost:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } }
3. 安全模块添加规则例外
如果你启用了ModSecurity、Nginx App Protect等WAF模块,给/proxy路径添加例外规则即可:
location /proxy { proxy_pass http://localhost:3000; # ModSecurity为例,关闭当前路径的规则检查,也可以单独移除拦截对应规则ID SecRuleEngine Off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; }
4. 验证配置生效
修改完配置后先执行语法检查,再重载配置生效:
nginx -t && nginx -s reload
重新发起带完整URL参数的请求即可正常响应。
额外优化:你之前写的301跳转规则要放在监听80端口的server块内,放在443块内会导致https请求死循环跳转,正确配置如下:
server { listen 80; listen [::]:80; server_name mydomain.com; if ($host = mydomain.com) { return 301 https://$host$request_uri; } }
内容的提问来源于stack exchange,提问作者Joshua Terrill
相关产品推荐
相关产品推荐

