Nginx 的 map 指令可基于客户端 IP 动态设置日志记录变量,配合 access_log 的 if 条件实现 IP 过滤;需在 http 块中定义 map,用 $remote_addr 或 $realip_remote_addr 映射 $loggable,再于 server 中通过 access_log ... if=$loggable 启用条件日志。

Nginx 的 map 指令可以高效地根据客户端 IP 动态设置变量,配合 access_log 的条件记录功能,就能实现灵活的基于 IP 的访问日志过滤——比如只记录特定 IP 或排除某些 IP 的请求,避免日志被无关流量刷满。
定义 IP 过滤逻辑用 map
map 指令必须放在 http 块中,它将 $remote_addr(或 $http_x_forwarded_for)映射为一个自定义变量(如 $loggable),值为 1 表示记录,0 表示跳过。支持 CIDR、精确 IP 和正则匹配:
- 默认设为 0(不记录),再显式列出需要记录的 IP 段
- 用
~前缀支持正则,例如过滤爬虫 UA 关联的 IP(需先提取 UA 或结合其他变量) - 注意:
map不支持嵌套或复杂表达式,逻辑尽量扁平
示例:
http {
map $remote_addr $loggable {
default 0;
192.168.1.100 1;
2001:db8::1 1;
10.0.0.0/8 1;
~^172\.1[6-9]\. 1; # 匹配 172.16.0.0–172.19.255.255
}
}在 server 或 location 中启用条件日志
使用 access_log 的第三个参数指定“记录条件”,引用上面定义的变量。Nginx 仅当该变量非空且非 0(或 "0" 字符串)时写入日志:
- 变量值为
1、"yes"、非空字符串→ 记录 - 变量值为
0、""(空字符串)、off→ 跳过 - 可同时配置多个日志文件,分别用不同
map变量控制
示例:
server {
access_log /var/log/nginx/access.log main if=$loggable;
# 其他配置...
}处理代理环境下的真实 IP
如果 Nginx 前有负载均衡或 CDN,$remote_addr 是上游地址而非用户真实 IP。此时需先通过 set_real_ip_from 和 real_ip_header 还原真实 IP,再在 map 中使用 $realip_remote_addr(需启用 http_realip_module):
- 确认已编译或启用了 realip 模块(常见于主流发行版包)
- 在
http或server块中配置信任的上游网段 -
map中改用$realip_remote_addr作为源变量
验证与调试技巧
直接查看变量值最可靠。可在响应头中临时输出变量用于调试(上线前务必移除):
- 加一行
add_header X-Loggable $loggable;,用 curl 观察返回头 - 检查 error.log 是否有
map相关警告(如变量重复定义、语法错误) - 用
nginx -t测试配置,用nginx -s reload平滑重载 - 日志文件不再增长 ≠ 过滤生效,要用已知 IP 主动请求并检查 access.log 是否出现


















