直接用 $request_uri 配合 Nginx 的 map 指令可实现轻量高效、不依赖后端的动态路径阻断:提取敏感路径共性(管理关键词、高危扩展名、敏感目录名、路径遍历痕迹),通过 map 映射为拦截开关变量,再在 server 块中用 if 判断返回 400。
直接用 $request_uri 配合 Nginx 的 map 指令做动态路径匹配,是轻量、高效且不依赖后端的阻断方式。关键在于把“敏感后台加密路径”的特征抽象成可匹配的规则,再通过 map 映射为状态码控制变量,最后在 server 或 location 块中统一拦截返回 400。
黑客扫描常针对形如 /admin/、/wp-admin/、/phpmyadmin/、/backup.zip、/config.php.bak 等路径。不要逐个写死,应提取特征:
%2e%2e/、..%2f)在 http 块中定义 map,将匹配结果映射为 1(需拦截)或 0(放行)。注意使用正则时开启 ~* 忽略大小写,并用 ^~ 或 ~ 确保优先级:
map $request_uri $block_sensitive_path { default 0; ~*^/(admin|manage|console|dashboard|backend|wp-admin|phpmyadmin|xamp|webmin|jenkins)/ 1; ~*.(bak|old|swp|git|env|log|sql|zip|tar.gz)$ 1; ~*../ 1; ~*%2e%2e/%2f 1; ~*.php.bak 1;}
该 map 变量值为 1 时,表示当前请求命中任一敏感模式。
无需修改每个 location,只需在 server 块顶部添加条件判断:
if ($block_sensitive_path) { return 400;}
注意:if 在 location 外可用,且 Nginx 官方明确允许在 server 级别用于简单变量判断。400 比 403 更合适——它表示客户端请求语法错误(如非法路径),符合扫描行为本质,也避免暴露“权限拒绝”语义。
防止绕过和误杀,建议补充以下细节:
~* /cgi-bin/.*? 1; 拦截带参数的 CGI 扫描$request_uri 做 decode 再匹配?Nginx 默认不解码 URI,若需解码匹配,改用 $uri(已解码且标准化)配合 map $uri
$block_sensitive_path,便于溯源分析不复杂但容易忽略的是匹配顺序和正则边界——用 ^/ 锚定开头,$ 锚定结尾,防止子串误匹配(如 /user/admin 不应触发 admin 规则,除非你明确要拦截所有含 admin 的路径)。