Nginx 无法直接过滤恶意扫描,但可通过 try_files 配合命名 location(如 @empty)返回 204 实现静默拦截;也可用 map + if 基于 URI 关键词匹配并 return 204,或用 location ^~ 快速拦截已知敏感路径。

Nginx 本身不提供“过滤恶意扫描”这一语义级别的能力,try_files 的作用是按顺序检查文件或路径是否存在,并返回第一个存在的资源;它不能主动识别“恶意”,也无法直接“返回空响应”(如 204 或空 body 的 200)。但你可以利用 try_files 配合其他指令(如 return、map、if)实现对常见扫描路径的静默拦截——即:不记录日志、不执行后端、不返回错误页,而是快速返回一个空响应(如 HTTP 204)。
用 try_files + named location 实现静默丢弃
这是最推荐的方式:将可疑路径映射到一个内部命名 location,在其中直接返回 204,避免走完整处理流程,也不触发日志(可选)。
- 在 server 块中定义常见扫描特征路径(如
/phpmyadmin/、/wp-login.php、/shell.php等),用location ^~或正则匹配提前拦截 - 或更通用的做法:用
try_files尝试一个不存在的文件,再 fallback 到一个命名 location,该 location 执行return 204
示例配置:
location / {
# 尝试找真实文件 → 若都不存在,则跳转到 @empty
try_files $uri $uri/ @empty;
}
<h1>命名 location:返回空响应且不记 access log</h1><p>location @empty {
access_log off; # 可选:不记录这类请求
return 204;
}</p>⚠️ 注意:try_files 本身不会“识别恶意”,它只是按路径是否存在做判断。要真正拦截扫描,需配合前置规则——比如把所有含 .php 但又不对应真实 PHP 文件的请求导向 @empty。
结合 map 和 if 实现关键词级静默拦截
若想根据 URI 中的关键词(如 phpmyadmin、mysql、shell)拦截,可用 map 提前标记,再用 if 跳转:
map $request_uri $is_scan {
~*(phpmyadmin|webshell|etc/passwd|\.git/config|wp-login\.php) 1;
default 0;
}
<p>server {
location / {
if ($is_scan) {
return 204;
}
try_files $uri $uri/ /index.php?$query_string;
}
}</p>✅ 优点:灵活匹配任意字符串模式
❌ 缺点:if 在 location 中有使用限制,且过度依赖正则可能影响性能;不建议用于高频核心路径。
补充建议:别只靠 try_files,组合防御更有效
- 用 location ^~ /xxx/ 快速拦截已知敏感路径,比 try_files 更早介入,效率更高
-
开启 Nginx 日志条件过滤:用
log_format+map把扫描请求设为access_log off,减少日志噪音 - 搭配 fail2ban 或 ngx_http_geo_module:对高频扫描 IP 做临时封禁,比单次返回 204 更治本
- 避免用 return 200 "":某些客户端会因空 body 异常,204 是语义上更标准的“无内容”响应
本质上,这不是 try_files 的本职工作,而是借它的 fallback 机制做轻量路由分发。真正的扫描防护需要分层设计:URI 规则拦截(快)→ 请求频率控制(准)→ 源头 IP 封禁(狠)。Nginx 做好第一关就够了。











