要让Prometheus采集Nginx的客户端真实IP和地理分布数据,核心是Nginx先还原真实IP并注入GeoIP字段,再通过Exporter暴露为指标:1.配置real_ip模块精准还原$realip_remote_addr;2.加载GeoIP2模块提取country/city并写入日志或map变量;3.用nginx-prometheus-exporter或Filebeat将地理维度转化为带label的Prometheus指标。

要让 Prometheus 采集 Nginx 的客户端真实 IP 和地理分布数据,核心不是让 Prometheus 直接“解析 IP”,而是由 Nginx 先完成真实 IP 还原与 GeoIP 标注,再通过 nginx-prometheus-exporter 或 自定义日志埋点 + log exporter 将结构化字段暴露给 Prometheus。整个链路必须分三步走:还原真实 IP → 提取地理位置 → 暴露为指标或标签。
确保真实 IP 已被正确还原
这是所有后续分析的前提。若 Nginx 的 $remote_addr 仍是 CDN 或 SLB 的 IP,GeoIP 查询将全部失效。
- 在
http块顶部声明可信上游网段(不能写0.0.0.0/0):set_real_ip_from 103.21.244.0/22;(Cloudflare)set_real_ip_from 192.168.0.0/16;(内网 LB)set_real_ip_from 203.0.113.50;(单个 WAF 出口 IP) - 指定原始 IP 来源头:
real_ip_header X-Forwarded-For;(标准代理)# real_ip_header CF-Connecting-IP;(Cloudflare 专用) - 启用递归解析(防多层伪造):
real_ip_recursive on; - 验证是否生效:加一个测试 location
location /debug/ip { return 200 "$realip_remote_addr\n"; }
访问确认返回的是公网 IPv4,而非 10.x 或 172.x 内网地址
用 GeoIP2 提取国家/城市并注入日志字段
Prometheus 本身不处理日志内容,但可通过日志格式嵌入结构化字段,再由 prometheus-log-exporter 或 mtail 提取为指标。
- 加载 MaxMind GeoIP2 数据库(需编译含
--with-http-geoip2-module的 Nginx):geoip2 /etc/nginx/GeoLite2-Country.mmdb {<br> $geoip2_data_country_code source=$realip_remote_addr country iso_code;<br> $geoip2_data_city_name source=$realip_remote_addr city names en;<br> } - 定义带地理字段的 log_format:
log_format geojson '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" ' '"$http_x_forwarded_for" ' '"$geoip2_data_country_code" "$geoip2_data_city_name"'; - 在 server 或 location 中启用该格式:
access_log /var/log/nginx/access_geo.log geojson;
将地理维度转化为 Prometheus 可采集指标
推荐两种轻量、免 Lua 的方案:
-
方案一:nginx-prometheus-exporter + 自定义 metrics(推荐)
启动 exporter 时开启--nginx.scrape-uri指向 Nginx stub_status,并配合 Nginx 的upstream状态;
若需按地域统计请额外配置:
在 Nginx 中用map将国家码映射为计数器变量:map $geoip2_data_country_code $country_requests {<br> default 0;<br> CN 1;<br> US 1;<br> JP 1;<br> }
再通过nginx-prometheus-exporter的--nginx.export-metrics功能暴露该变量为指标nginx_country_requests_total{country="CN"} -
方案二:Filebeat + Prometheus Exporter(适合已有 ELK 架构)
Filebeat 读取access_geo.log,用 dissect 或 grok 解析出country_code字段;
推送至prometheus-log-exporter,配置 label 映射规则:labels: {country: "${country_code}", city: "${city_name}"}
自动生成指标如nginx_http_requests_total{country="DE",city="Frankfurt"}
注意事项与避坑点
不配置信任网段就开 real_ip_recursive on,会导致 IP 被伪造;不校验 $realip_remote_addr 是否为公网地址,GeoIP 查询会返回空或错误值。
- 务必禁止
set_real_ip_from匹配任意公网 IP(如0.0.0.0/0),否则攻击者可伪造X-Forwarded-For绕过限流 - GeoIP2 模块默认不支持 IPv6 地址查询,如需兼容请确认数据库版本及模块编译参数
- 若使用 Cloudflare,优先用
CF-Connecting-IP头 +set_real_ip_from对应 ASN 段,比依赖X-Forwarded-For更可靠 - Prometheus 抓取频率建议 ≥15s,避免高频采样导致 Nginx 日志 I/O 压力突增


















