disable_symlinks 不是禁止符号链接,而是仅在 alias 或 root 解析路径时实时校验最终路径是否越出 from= 指定的绝对目录,越界即返403;必须置于 location 或 server 块中,不支持 http 块,且仅对 nginx 自身文件操作(如 try_files、open_file_cache)生效,对 proxy_pass 等无效。

disable_symlinks 不是“禁止符号链接”,而是防止 Nginx 在读取文件时被软链带出可信目录范围。它不删除、不屏蔽链接本身,只在 alias 或 root 解析路径的那一刻做实时校验——一旦最终路径落在 from= 指定目录之外,立刻返回 403,不继续读取。用错位置或脱离上下文,它就完全不生效。
必须放在 location 或 server 块里,且紧挨 root/alias
该指令不能写在 http 块中,Nginx 启动会直接报错:"disable_symlinks" directive is not allowed here。因为它需要两个运行时信息:当前请求 URI 和实际生效的文件根路径(由 root 或 alias 提供)。只有 location/server 块才同时具备这两者。
- 正确示例(配合 alias):
location /static/ {<br> alias /var/www/static/;<br> disable_symlinks on if_not_owner from=/var/www/static/;<br>}
- root 场景下也有效,但要注意路径拼接逻辑是否可控;若 root 动态拼接(如
root /var/www/$arg_path),disable_symlinks 将不触发 -
from=必须是绝对路径,末尾斜杠建议保留(如/var/www/static/),避免因路径截断导致误判
推荐开启 if_not_owner 增强权限控制
仅写 disable_symlinks on from=... 能防跨目录,但无法阻止同目录下恶意用户创建指向敏感文件的软链(比如把 /var/www/static/hack 指向 /etc/passwd)。加上 if_not_owner 后,Nginx 还会检查软链目标文件的所有者是否与 worker 进程用户(如 www-data)一致。
- 启用后,即使软链在
from目录内,只要目标文件不属于 Nginx 用户,访问仍被拒绝 - 需确保静态目录下所有真实文件和软链本身都由 Nginx 用户拥有,否则正常链接也会被拦
- 适用于多用户共用上传目录、CMS 插件目录等存在第三方写入风险的场景
它只对 Nginx 自己读文件的行为起作用
disable_symlinks 是在 open() 系统调用阶段介入的,因此只影响 Nginx 原生文件操作,例如:
-
alias和root后的路径解析 -
try_files列表中的文件检查 -
open_file_cache缓存路径验证
它对以下情况完全无效:
-
proxy_pass、fastcgi_pass等反向代理类指令(那是后端的事) - PHP 的
file_exists()、readfile()等函数(需在应用层加固) - Apache 的
FollowSymLinks行为(那是另一套机制)
常见误区与绕过风险提醒
别以为加了就万事大吉。这些情况会让 disable_symlinks 形同虚设:
- SELinux 或容器环境(如 Podman)中策略拦截,导致检测逻辑被系统级拒绝,需查
error.log是否有Permission denied类提示 - 使用 overlayfs 等非标准文件系统,或 ext4 挂载时启用了
user_xattr,部分 symlink 检测可能静默失效 - 攻击者结合
../和软链嵌套(如a → b → /etc/passwd),若配置未覆盖全部跳转路径,仍可能越界 - 没配
if_not_owner,且攻击者能往静态目录写软链,就等于白开










