一个nginx geoip2问题
贵司一直使用geoip2的库来判断用户访问国家的来源。之前报问题过来发现都是来自ipv6的问题。
那怎么想的,估计是这个geoip2的库不准导致的,或者压根就没ipv6的数据。
于是就过了那么多年,今天又有人反馈了,于是就仔细去看了下。
首先这个geoip2的库实在太老了,都4年多没更新了,那就给更新一下,发现还是不行。
然后又去看了一下nginx配置,仔细验证了配置内容,发现nginx配置也没有问题。
那就重新来考虑吧,先看看geoip2库是否有问题。发现人maxmind特别贴心,https://github.com/maxmind/GeoIP2-python 这上面代码都给你写好了。
把客户的ipv6地址贴进去,发现返回值是正确的。
接着看了下日志,发现ipv4的来源ip都是记录在remote_addr里的,而ipv6的却是记录在X-Forwarded-For里的,并且remote_addr里是云厂商的slb的ip地址。把云厂商的slb的ip地址贴近geoip2库里解析,直接就报错了。
1 | Traceback (most recent call last): |
得了,那估计可能是这个问题了。但是为什么ipv6和ipv4的入口来源会不一致呢,翻看了slb配置,我去,这一个是4层转发,一个是7层转发。4层转发是透传client ip过来的,而7层是放在header里面的。
那是不是解法就是把ipv6的7层转发改成4层就行了? 可这样不好的后果就是本来slb可以帮你卸载tls,现在要你自己来了。这样不符合我们能省则省的精神啊。
于是再翻看一下nginx geoip2库的文档。
https://github.com/leev/ngx_http_geoip2_module
发现原来跟geoip是一样的。只要写上slb的ip,那就直接从X-Forwarded-For来取了,聪明的老铁肯定会问,如果X-Forwarded-For用逗号写了多个ip,那它会怎么取呢?
同时还发现一个mmdblookup的工具,连上面python代码都不用写,直接就命令行用上了。
https://maxmind.github.io/libmaxminddb/mmdblookup.html
1 | geoip2_proxy 100.64.0.0/10; |
人这里写的很清楚了,就取最新的那个ip,也就是最近的那个。
最后就把那堆4层代理都转成7层代理就算正式收工了。