Nginx之ngx_http_geo_module
官方文档:http://nginx.org/en/docs/http/ngx_http_geo_module.html
ngx_http_geo_module模块的主要功能为:根据ip地址赋值(创建)变量。此ip可以是客户端ip,也可以是其数据来源的ip地址(例如:可以是query参数ip,也可是cookie里面的ip、也可以是header头的ip)。此模块不但支持ipv4的ip格式,也支持ipv6的ip格式(>=1.3.10,>=1.2.7)
安装
默认情况下nginx会自动安装的此模块,除非你在安装的时候显示排除此模块安装(–without-http_geo_module)
geo语法:
Syntax: geo [$address] $variable { ... } Default: — Context: http
geo 后跟2个参数, ip地址(第一个参数) + 变量(第二个参数,需要赋值的变量名称)。
语法需要重点关注的点是:
1、 第一个参数可以省略,省略值默认为:$remote_addr。 geo $country = geo $remote_addr $country
2、 此语法只能在http上下文配置。不可配置在server或者location上下文中。
3、 参数必须是有效的ip地址,如果是非法格式,将直接转化为“255.255.255.255”的地址
4、 大括号里面是放的是kv结构体,用于匹配并赋值。k理解规则,v理解为对应的值
kv结构体除了支持基本的ip地址(地址段),可支持如下特殊参数:
delete:
用于删除指定的网络
default:
如果ip与所有规则都不匹配,将会匹配此规则。类似于switch语法的default语句。如果没有匹配任何规则,也未设置default,将给变量赋值空字符串“”。
include:
包含的的文件,文件内容也需是kv结构体。
proxy:
定义可信地址。 如果请求来自可信地址,nginx将使用其“X-Forwarded-For”头来获得地址。 相对于普通地址,可信地址是顺序检测的。
proxy_recursive:
开启递归查找地址。 如果关闭递归查找,在客户端地址与某个可信地址匹配时,nginx将使用”X-Forwarded-For”中的最后一个地址来代替原始客户端地址。如果开启递归查找,在客户端地址与某个可信地址匹配时,nginx将使用”X-Forwarded-For”中最后一个与所有可信地址都不匹配的地址来代替原始客户端地址。
ranges:
使用以地址段的形式定义地址,这个参数必须放在首位。为了加速装载地址库,地址应按升序定义。
样例
官方demo1:
geo $country { default ZZ; include conf/geo.conf; delete 127.0.0.0/16; proxy 192.168.100.0/24; proxy 2001:0db8::/32; 127.0.0.0/24 US; 127.0.0.1/32 RU; 10.1.0.0/16 RU; 192.168.1.0/24 UK; }
文件conf/geo.conf内容:
10.2.0.0/16 RU; 192.168.2.0/24 RU;
demo解析:此配置根据用户不同的ip地址确定用户所处的国家,其中使用delete参数排除了本机ip、include参数引入了其他配置信息、proxy定义可信任的ip段(代理机)。
官方demo2:
geo $country { ranges; default ZZ; 127.0.0.0-127.0.0.0 US; 127.0.0.1-127.0.0.1 RU; 127.0.0.1-27.0.0.255 US; 10.1.0.0-10.1.255.255 RU; 192.168.1.0-192.168.1.255 UK; } server { listen 8000; default_type text/plain;- location / { echo $remote_addr; echo $country; } }
释义:方法体使用ranges的特殊参数,此参数约定将以地址段的形式匹配ip地址。在官方文档中,地址段可以出现交集,最终以最匹配的为准,但在实际验证中,地址段是不能出现交接的。请各位看官注意。
(注:每个国家都有特定的ip网段,各个省份地区也有特定的ip网段。可以百度‘各省ip地址’段查看具体信息)
依据ranges功能,即可根据已知的地址段,再结合geo命令即可实现ip区域定位功能。
如上所说,除了可以判定入参($arg_{variable })ip归属地,可以根据header头($http_{$variable })或者cookie($cookie_{$variable })的某值确定归属地
注:会有很多人疑问,在业务逻辑中只有某一个api(location)会使用此ip赋值功能,将此赋值卸载http上下文中岂不是会影响整体的性能?
再次特别说明:配置过多的geo变量并不会给程序带来额外的性能消耗,程序只有在调用此便令的时候才会对其进行计算赋值。也就是说只有在特定需要此geo功能的location才会触发赋值。