Nginx防目录遍历需在proxy_pass前拦截恶意路径:顶层用if校验$uri和$request_uri中..、编码变体及//;location须精确匹配如^~/api/v1/;禁用autoindex;黑名单敏感路径;文件下载应结合internal与签名URL。

在 Nginx 反向代理场景下防目录遍历,核心不是“代理后过滤”,而是**让恶意路径在进入 proxy_pass 前就被拦截**。因为一旦请求被转发给后端(如 PHP-FPM、Node.js 或静态文件服务),Nginx 就失去了对路径解析的控制权,此时再拦已无意义——攻击者可能已触发后端的文件读取逻辑。
严格校验原始 URI,拒绝一切穿越特征
必须在 server 块顶层(不在任何 location 内)用 if 指令做最早期拦截,覆盖解码后和原始请求中的所有常见变体:
-
if ($uri ~ "\.\.") { return 403; }—— 拦截标准化路径中含..的请求(如/api/../../etc/passwd) -
if ($request_uri ~ "(\.\.\/|\/\.\.|%2e%2e|\.%2e|\/%2e%2e)") { return 403; }—— 覆盖 URL 编码、混合写法(如/%2e%2e/etc/passwd) -
if ($uri ~ "//") { return 403; }—— 防双斜杠干扰路径归一化(如//../etc/passwd)
反向代理 location 必须显式限定路径前缀
避免使用宽泛匹配(如 location /),而应为代理路径设置明确、不可越界的入口点:
- 正确示例:
location ^~ /api/v1/ { proxy_pass http://backend; }——^~确保前缀匹配优先,不被正则 location 覆盖 - 禁止写法:
location / { proxy_pass http://backend; }—— 容易被/../.env这类路径绕过,且无法区分静态资源与 API - 若需代理动态路径,加白名单校验:
location ~ ^/download/[a-zA-Z0-9._-]+\.pdf$ { proxy_pass http://files; }
禁用 autoindex,屏蔽敏感路径前缀
即使走代理,也要防止 Nginx 自己暴露目录结构或响应非法路径:
- 全局关闭目录列表:
autoindex off;放在http或server块顶部 - 在所有
proxy_pass规则之前,加黑名单 location:location ~ ^/(?:\.(git|svn|env)|config|backup|logs|phpmyadmin) { return 403; } - 特别注意:该 location 必须放在
location /api/等代理规则之前,否则会被“最长前缀匹配”跳过
后端路径隔离 + internal 机制兜底
对于确需提供文件下载但又不能暴露真实路径的场景(如用户上传附件),不要直接代理到磁盘路径,而应:
- 将真实文件存于 Web 根目录外(如
/var/www/private/uploads/) - 用
internal;声明专用 location:location /protected/ { internal; alias /var/www/private/uploads/; } - 由后端应用(如 PHP 脚本)生成带签名的临时 URL,再用
rewrite+proxy_pass转发至该internal区域


















