internal指令是nginx的“内部工牌”校验机制,只允许rewrite last、auth_request子请求和x-accel-redirect三种内部跳转访问,外部直连一律返回404;必须置于具名location块中,不可单独使用或放在泛匹配块内,且需配合外层鉴权与合法跳转逻辑才能真正生效。

internal 指令不是给接口加密码,而是把入口关死——只认 Nginx 自己发来的“内部工牌”,不看 Token、不验 IP、也不管你带没带 Cookie。外部浏览器或 curl 直连,一律返回 404;只有 rewrite last、auth_request 成功后的子请求、X-Accel-Redirect 响应头这三种方式触发的跳转,才能进门。
必须放在具名 location 里,不能裸用
internal 只能在明确路径前缀的 location 块中生效,比如 location /_internal/ { internal; ... }。它不能写在 server 或 http 块顶层,也不能塞进 location / { } 这类泛匹配块里。否则要么无效,要么引发循环重写。
- 正确写法:location ^~ /_api/ { internal; proxy_pass http://backend; }
- 错误写法:internal; 单独一行;或 location / { internal; ... }(易导致匹配错乱)
靠内部跳转触发,不是靠路径隐藏
它不靠“藏地址”起作用,而是靠“谁发起请求”来判断。真正的入口得另设一个普通 location,负责做鉴权、路由或参数解析,再用合法机制跳进来。
- 有效跳转方式:rewrite ... last(注意是 last,不是 redirect)、auth_request 鉴权后隐式流转、X-Accel-Redirect 响应头驱动
- 无效跳转方式:proxy_pass 直连、302 跳转、curl 手动请求 /_internal/ 路径
要配合外层逻辑才真正安全
单独加 internal 不等于保险。如果外层 location 没做鉴权就直接 rewrite last,攻击者仍可能构造合法 URL 绕过;如果同时存在另一个 location 把同一后端暴露出去,internal 就形同虚设。
- 推荐组合:外层 location + auth_request → 内层 location = /auth { internal; ... } → 后续跳转到 /_internal/
- 常见漏洞点:/auth 接口本身没加 internal,被直接调用;或 /_internal/ 路径被其他 location 以 proxy_pass 方式间接暴露
验证是否生效很简单
部署后立刻做两件事:
- curl https://example.com/_internal/test → 应返回 404
- curl https://example.com/api/v1/test(该路径经 rewrite last 跳转到 _internal)→ 应正常返回数据
- 查 access_log:若 /_internal/ 出现 200 记录,说明配置失效;若大量 404,可能是扫描行为











