map模块不直接执行访问控制,而是将请求特征(如IP、URL、User-Agent等)映射为变量值,再配合if、return或error_page实现差异化响应策略;首个匹配项生效,不支持嵌套“或”逻辑。

在 Nginx 中,map 模块本身不直接执行访问控制或返回错误,但它能高效地将请求特征(如 IP、URL、User-Agent、请求头等)映射为变量值,再配合 if、return、deny 或 error_page 实现差异化响应策略。关键在于:用 map 做“行为分类”,再用条件逻辑触发对应处置。
用 map 识别并标记违规类型
先定义一个映射规则,把不同违规特征转成可识别的标记(如 bad_ip、scan_path、sql_inject),便于后续统一判断:
map $remote_addr $violation_type {
default "";
192.168.1.100 "bad_ip";
203.0.113.55 "bad_ip";
~^192\.168\.2\.\d+ "rate_abuse";
~*\/admin\/.*\.php$ "unauthorized_admin";
~*(select|union|sleep\(\)|benchmark\() "sql_inject";
~*\/wp-content\/.*\.php$ "php_file_leak";
}说明:
• $remote_addr 可换成 $args(查询参数)、$request_uri(路径)、$http_user_agent(UA)等;
• 正则匹配用 ~(区分大小写)或 ~*(忽略大小写);
• 多个条件可叠加,但注意 map 执行顺序:**首个匹配项生效,不支持“或”逻辑嵌套**。
结合 if 和 return 实现差异化响应
map 生成的变量可在 server 或 location 块中使用 if 判断,并用 return 直接返回指定状态码和内容:
-
对扫描类行为返回 403 + 自定义提示:
if ($violation_type = "scan_path") { return 403 "Access denied: suspicious path access."; } -
对 SQL 注入特征返回 444(静默断连):
if ($violation_type = "sql_inject") { return 444; } -
对恶意 IP 返回 403 并记录日志(需配合 log_format):
if ($violation_type = "bad_ip") { return 403; }
⚠️ 注意:if 在 location 中可用,但在 server 级别慎用(Nginx 官方建议限制其使用范围);return 会终止当前请求处理,优先级高于 rewrite 或 proxy_pass。
用 error_page 统一处理并区分响应体
若需返回不同 HTML 页面或 JSON 错误,可配合 error_page + 内部重定向:
map $violation_type $error_page {
default "/_default_403.html";
"sql_inject" "/_sql_blocked.html";
"rate_abuse" "/_rate_limited.html";
"bad_ip" "/_ip_banned.html";
}
<p>server {
...
error_page 403 /custom_403;
location = /custom_403 {
internal;
root /usr/share/nginx/html;
try_files $error_page =404;
}</p><pre class="brush:php;toolbar:false;"># 触发方式(例如)
if ($violation_type != "") {
return 403;
}}
这样,不同违规类型最终渲染不同静态页面,运维和前端可分别定制提示文案与样式,也便于 A/B 测试拦截效果。
补充:与 realip_module 配合处理代理后的真实 IP
如果 Nginx 前有 CDN 或 LB,$remote_addr 是代理 IP,需先还原真实客户端 IP:
- 启用
ngx_http_realip_module(编译时默认开启); - 配置:
set_real_ip_from 192.168.0.0/16;(信任的代理网段);real_ip_header X-Forwarded-For;; - 之后
map中用$realip_remote_addr替代$remote_addr进行匹配。
否则基于代理 IP 的封禁会误伤整个 CDN 节点下的所有用户。


















