internal指令让敏感路径对扫描器彻底“不可见”,外部直连一律404,不暴露存在性;必须置于具名location块内,且仅响应rewrite last、auth_request等内部跳转。

用 internal 指令防恶意扫描,核心不是“挡住扫描器”,而是让敏感路径对扫描器彻底“不可见”——它不返回 403,连存在都不承认,直接 404。扫描工具扫到 /internal-api/ 或 /_protected/,只会记下“路径不存在”,无法确认后端是否真实部署,从而大幅降低被定向攻击的风险。
为什么 internal 能有效对抗路径扫描
普通 deny / return 403 会暴露路径存在;internal 则从机制上切断客户端直连能力:
- 外部请求无论带不带 Token、Referer、合法 Cookie,甚至伪造 Host 头,一律返回 404 Not Found
- 目录爆破、爬虫遍历、自动化扫描工具拿到的全是“404”,无法区分是真不存在,还是被保护
- 不依赖 IP 白名单或 Header 校验,避免规则绕过,逻辑更干净
正确配置 internal 的两个硬性前提
internal 不是开关,而是“通行许可章”,必须满足以下两点才生效:
- 必须写在具名
location块内(如location /_internal/ { ... }),不能放在server或http根上下文里 - 该 location 必须通过 Nginx 内部跳转才能命中——比如
rewrite ... last、auth_request成功后流转、try_files回退、或后端返回X-Accel-Redirect头
典型防扫描结构:对外入口 + 对内隐身
不能只加 internal 就完事,要构建两段式链路:
-
对外入口 location:例如
location ^~ /api/,负责接收请求,可加auth_request /auth鉴权,再用rewrite ^/api/(.*)$ /_internal/$1 last;跳转 -
对内隐身 location:例如
location ^~ /_internal/ { internal; proxy_pass http://backend; },不处理任何逻辑,只做透传,外部直连即 404
这样,扫描器扫 /_internal/health 得到 404;但正常用户调 /api/health 经鉴权和内部重写后,能成功到达后端。
避坑要点:这些错误会让 internal 彻底失效
- 在
internallocation 中用了rewrite ... redirect(302)——这是浏览器重发,不算内部跳转 - 把
internal放在location / { ... }这种根路径下,导致整个站点打不开 - 用
root而非alias配合internal提供静态文件,路径拼接易出错(推荐用alias /data/protected/;,且 location 末尾斜杠需与 alias 一致) - 未给
auth_request子请求 location 加internal,攻击者可绕过主入口直接请求鉴权地址

















