apache日志需通过真实客户端ip结合geolite2或nali等地理库解析国家/地区;须用x-real-ip替代%h记录真实ip,再批量查库获取归属地,referer不可用于地域判断。

Apache 日志本身不直接记录国家/地区,但可以通过日志中的客户端 IP 地址 + 外部地理库(如 GeoLite2 或 nali)反查归属地。关键分两步:确保日志里有真实 IP,再用工具批量解析。
确保日志记录的是真实客户端 IP
如果网站前面有 CDN、Nginx 反代或负载均衡,$h(%h) 默认记录的是代理 IP,不是访客真实 IP。必须改用 %{X-Real-IP}i 或 %{X-Forwarded-For}i(注意后者可能被伪造,需服务端校验)。
在 Apache 配置中调整 LogFormat,例如:
LogFormat "%{X-Real-IP}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" realip_combined
CustomLog /var/log/apache2/access.log realip_combined
修改后 reload Apache(sudo systemctl reload apache2),新日志才含真实 IP。
提取高频 IP 并批量查地理信息
先从日志中抽取出需要分析的 IP 列表(比如最近 1 小时内请求最多的前 100 个):
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
awk -v d="$(date -d '1 hour ago' '+%d/%b/%Y:%H')" '$4 > "["d {print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -nr | head -100 | awk '{print $2}' > top_ips.txt
再用 mmdblookup(推荐,准确、支持 ASN)或 nali(轻量、中文友好)批量查:
- 用 GeoLite2-Country.mmdb 查国家码:
while read ip; do echo "$ip $(mmdblookup --file GeoLite2-Country.mmdb --ip $ip country iso_code 2>/dev/null | tr -d '"\n')"; done ip_country.csv - 用 nali(输出中文地区):
while read ip; do echo "$ip $(nali $ip)"; done ip_location.txt
注意:GeoLite2 免费数据库每月需手动更新;nali 的 IP 库也建议定期同步。
快速验证单个 IP 的归属地
排查某个异常 IP 时,不用跑完整流程,直接查:
-
mmdblookup --file /usr/share/GeoIP/GeoLite2-Country.mmdb --ip 203.123.45.67 country names en→ 返回 "China" -
nali 8.8.8.8→ 返回 "美国 加利福尼亚州圣克拉拉县山景市DNS服务器DNSPod节点"
结果中若显示 "reserved" 或空,说明该 IP 属于私有地址段(如 192.168.x.x)、局域网或未分配地址,无需地理定位。
注意 Referer 不等于来源国家
有人误以为日志里的 Referer 字段(如 https://google.com)能反映访客地理位置——其实不能。Referer 是上一页 URL,和用户在哪上网无关。它只说明“从哪个页面点进来的”,常为空(直连、HTTPS→HTTP 跳转、隐私模式等),且可被任意伪造。
真正判断地域,唯一可靠依据是 IP 地址本身,而非 Referer、User-Agent 或路径参数。










