internal指令不鉴权只守门,确保location仅响应内部跳转(如auth_request、rewrite last、error_page或x-accel-redirect),拒绝客户端直连;直连即返回404。

internal 指令本身不鉴权,只守门——它确保 location 只能被内部跳转触发,不能被客户端直连。真正在做权限判断的,是 auth_request、rewrite last 或后端服务返回的 X-Accel-Redirect。
为什么直接加 internal 就报 404?
因为 internal 的语义很硬:只要请求不是来自 Nginx 内部机制(比如 auth_request 子请求成功后的放行、rewrite ... last、error_page 或 X-Accel-Redirect 响应头),Nginx 就直接拒绝,返回 404(或 403,取决于是否配了 return 403)。
常见误操作:
- 浏览器手动访问
/_protected/xxx.pdf→ 必然 404 - 在
location /download/里写proxy_pass http://backend却没透传鉴权结果 → 后端返回 200 但没带X-Accel-Redirect→ Nginx 不知道要跳哪,也不触发 internal location -
internal写在了没被任何内部跳转命中的 location 下 → 形同虚设,还可能掩盖真实错误
auth_request + internal 是最稳的组合
这是纯 Nginx 原生能力就能落地的方案,不需要 Lua 或额外模块。核心在于把鉴权逻辑下沉到子请求,主流程保持轻量。
关键配置片段:
location ^~ /download/ {
auth_request /auth;
auth_request_set $upstream_status $upstream_status;
}
location = /auth {
internal;
proxy_pass http://auth-service;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
}
location ^~ /_protected/ {
internal;
alias /var/www/protected/;
}
说明:
-
auth_request触发子请求,只有返回 2xx 才继续;401/403 直接拦截 -
/auth必须加internal,否则攻击者可绕过主入口直接打它 -
/_protected/的alias路径末尾不加斜杠,否则文件拼接会出错(如alias /path/;+ 请求/_protected/a.txt→ 实际读/path/a.txt;若写成alias /path;→ 读/patha.txt)
X-Accel-Redirect 更适合后端动态控制路径
当文件路径需由业务逻辑实时生成(比如按用户 ID 分目录、带时效 token 的临时路径),用响应头驱动比 rewrite 更灵活。
后端返回示例(Java Spring Boot):
response.setHeader("X-Accel-Redirect", "/_protected/user_123/report_20260423.pdf");
response.setHeader("Content-Disposition", "attachment; filename=report.pdf");
response.setStatus(200);
Nginx 配置只需匹配这个 header:
location ^~ /_protected/ {
internal;
alias /var/www/protected/;
}
注意点:
-
X-Accel-Redirect的值必须以/_protected/开头,且严格匹配 location 前缀 - 后端不能返回完整文件系统路径(如
/var/www/protected/...),Nginx 会拒绝解析 - 如果用了
root而非alias,路径计算逻辑不同:root /var/www;+X-Accel-Redirect: /protected/xxx→ 实际读/var/www/protected/xxx
容易被忽略的性能与安全细节
透传大文件时,internal location 本身不处理内容,但 Nginx 仍需做磁盘 I/O 和网络发送。几个关键调节点:
- 加
sendfile on;(默认开启),避免内核态到用户态拷贝 - 对下载限速用
limit_rate 512k;,别放在server级,否则影响所有流量 - 禁用日志减少 IO:在 internal location 里加
access_log off; - 如果用
alias,确保路径不包含符号链接,否则可能绕过internal限制(Nginx 7+ 默认禁止,但老版本需确认)
真正的风险不在 Nginx 配置本身,而在于鉴权服务是否校验了原始 URI、HTTP 方法、用户上下文——internal 再严,也防不住上游放行了不该放的请求。











