用好 root 指令防目录遍历的关键是路径归属、访问控制和解析逻辑三者对齐:root 必须指向权限收紧的专用目录,配合 location + try_files 限定真实文件访问,并通过 if 规则早期拦截 ../ 等遍历特征,同时禁用 autoindex 和屏蔽敏感路径。

用好 root 指令防目录遍历,关键不是写法多复杂,而是路径归属、访问控制和解析逻辑三者必须对齐。它本身不防越权,但配错就等于敞开大门。
路径归属与文件系统权限必须收紧
root 指向的目录(如 /usr/share/nginx/html)不能是宽泛可写的区域:
- 所有者设为
root,所属组设为nginx或专用业务组:chown -R root:nginx /path/to/root - 目录权限设为
750:root 可读写执行,nginx 组仅可读执行,其他用户无任何权限 - 目录内静态文件统一设为
640,禁止执行位,避免泄露备份文件、配置片段或调试日志 - 绝对禁止将
root指向/etc、/var/log、用户家目录或系统根目录
location + root + try_files 是黄金组合
单独写 root 没意义,必须嵌套在 location 块中,并强制搭配 try_files:
-
location必须以斜杠结尾,例如location /static/ { ... },不能是/static -
root值末尾不加斜杠,例如root /var/www;,不是/var/www/ - 必须写
try_files $uri =404;—— 它让 Nginx 只响应真实存在的文件,不回退、不拼接、不列目录 - 这样即使请求
/static/../etc/passwd,Nginx 会尝试访问/var/www/static/../etc/passwd,但该路径不存在,直接返回 404,不会穿透
主动拦截非法路径特征
别等路径解析完再判断,要在早期阶段就阻断典型遍历模式:
- 在
server块顶部(所有location之前)加:if ($uri ~ "\.\.") { return 403; } - 补充覆盖 URL 编码变体:
if ($request_uri ~ "(\%2e\%2e|\.%2e|\/\%2e\%2e)") { return 403; } - 同时拦截双斜杠干扰:
if ($uri ~ "//") { return 403; } - 注意:
$uri是解码后标准化路径,$request_uri是原始请求串,两者配合更可靠
屏蔽敏感路径并关闭自动索引
即便没被遍历成功,直接猜路径也可能泄露信息:
- 全局禁用目录列表:
autoindex off;放在http或server块顶层,不要依赖默认值 - 在
server块靠前位置加黑名单:location ~ ^/(?:\.(?:git|env|htaccess)|config|backup|logs|phpmyadmin) { return 403; } - 正则以
^/开头锚定,避免误杀正常路径中的子串(如/api/config/v1不会命中) - 所有静态资源
location内也显式写autoindex off;,防止继承异常
不复杂但容易忽略。核心就是让 Nginx 只能看见你让它看见的那部分文件系统,且只响应真实存在的文件。


















