Nginx反向代理中应通过if+$request_method在location块内拦截非必要HTTP方法,如仅允GET/HEAD/POST,禁用TRACE/PUT/DELETE等,并按路径差异化控制,返回405更语义准确。

在 Nginx 反向代理中限制 HTTP 请求方法,不是靠后端判断,而是由 Nginx 在代理前就完成拦截——这是应用层防御的关键一环,能直接阻断 OPTIONS、PUT、DELETE、TRACE 等非必要或高危方法,减少后端暴露面和误触发风险。
用 if + $request_method 严格过滤方法
最直接有效的方式是在 location 块中使用 if 判断请求方法,匹配即拒绝:
- 只允许 GET、HEAD、POST:
if ($request_method !~ ^(GET|HEAD|POST)$) { return 405; } - 禁止 TRACE 和 TRACK(常用于 XSS 探测):
if ($request_method ~ ^(TRACE|TRACK)$) { return 405; } - 注意:
if在 location 内可用,但不建议在 server 或 http 级滥用;返回 405(Method Not Allowed)比 403 更语义准确,也避免泄露服务逻辑。
结合 location 路径做差异化控制
不同路径对方法的要求不同,应分而治之:
-
/api/v1/users/允许 POST/PUT/DELETE,但需鉴权,可先放行再交由后端处理; -
/static/或/images/只允许 GET 和 HEAD:location ^~ /static/ { if ($request_method !~ ^(GET|HEAD)$) { return 405; } proxy_pass http://static_backend; } -
/admin/下全面禁用非安全方法:location ^~ /admin/ { if ($request_method ~ ^(PUT|DELETE|PATCH|TRACE|OPTIONS)$) { return 405; } proxy_pass http://admin_backend; }
配合其他应用层规则增强实效
单靠限方法不够,要和内容特征联动才防得住绕过:
- 对含
Content-Type: application/json且方法为 POST 的请求,可额外校验 body 是否含恶意关键字(需配合 lua-nginx-module 或外部 WAF); - 禁止未带
Content-Length却声称有 body 的请求(如空 POST):if ($request_method = POST) { if ($content_length = "") { return 400; } } - 搭配
limit_except指令更简洁(适用于简单场景):location /upload/ { limit_except GET POST { deny all; } proxy_pass http://upload_backend; }
避免常见陷阱
几个容易出问题的细节必须注意:
-
limit_except仅作用于当前 location,且内部不支持变量或正则,灵活性不如if; - 不要在
if中嵌套proxy_pass,Nginx 会报错;所有代理动作必须写在if外; - 若启用了 WebDAV 模块,需确认是否真需要 PROPFIND、MKCOL 等方法,否则建议彻底禁用该模块(
./configure --without-http_dav_module); - 前端发预检请求(CORS OPTIONS)时,需单独放行:
if ($request_method = OPTIONS) { add_header Access-Control-Allow-Origin "*"; add_header Access-Control-Allow-Methods "GET, POST, OPTIONS"; add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization"; add_header Access-Control-Max-Age 1728000; add_header Content-Length 0; add_header Content-Type text/plain; return 204; }


















