最近在处理站点的连接优化问题,需要通过检测访问者的 IP ,来选择是否经由 CloudFlare 代理,还是通过一个优化的直连地址进行体验优化。经过一些资料的比对,最终决定使用 GeoIP2 分辨来访者 IP 归属地,并通过 nginx 设置对应的规则来跳转访问。
背景提要
GeoIP2 是 MaxMind 公司推出的知名 IP 定位数据库,有提供免费的 Lite 版本可供下载使用(需要注册),数据库每周更新。
请注意如果您使用了免费下载的 GeoLite2 数据库,您需要遵循 Creative Commons 4.0 的授权使用原则,在您使用到了该数据库的项目/页面上标注 MaxMind 的宣传(可在下载页面看到),自觉遵守使用协议从我做起。
nginx的版本比较重要,低于1.9.11
版本的nginx无法使用动态模块,低于1.11.5
版本的nginx编译动态模块时不支持--with-compat
兼容参数,所以请保证您的nginx版本不低于1.11.5
。
比较推荐的做法是使用稳定的主要版本,可以在nginx的官方网站上找到对应Linux系统的包管理软件安装教程。
本文中使用的下载方式是 wget ,您也可以选择使用其他的下载方案。
准备代码
准备一个工作目录
一个工作目录有助于保持环境的干净,防止其他项目的干扰,并且在不再需要时移除也比较方便。
假设我们是 root 用户,登入VPS后没有做什么其他的工作,那么我们当前的目录是 /root/
;
我们创建一个名为 nginx
的工作目录,并进入,那么我们现在的目录应当就是 /root/nginx/
。
可以稍微留一个心眼,之后编译构建的时候,我使用到的是绝对路径。
安装libmaxminddb
这是一个用于 C 语言读取 MaxMind 数据库的资源包,编译插件时需要使用。这里只介绍最简单的安装方式,如有出现任何问题您可以查询原始页面的说明,或是在评论区回复,一起定位出错点。
从Release下载
libmaxminddb-*.tar.gz
的文件,例如我使用的是libmaxminddb-1.5.2.tar.gz1
wget https://github.com/maxmind/libmaxminddb/releases/download/1.5.2/libmaxminddb-1.5.2.tar.gz
解压文件,进入目录
1
2tar zxvf libmaxminddb-1.5.2.tar.gz
cd libmaxminddb-1.5.2/编译安装
1
2
3
4
5./configure
make
make check
make install
ldconfig退出目录
1
cd ../
下载 pcre 、 zlib 和 openssl
nginx 的编译需要这三大模块的参与,缺少会导致在配置阶段就报错,因而建议分别下载并解压。
请注意 nginx 使用的是 openssl 1 的头文件,似乎还不支持 openssl 3 ,请还是选择 1.1.1j 版本吧。
名称 | 官网地址 | 下载地址 | 截稿时的最新软件包 |
---|---|---|---|
pcre | pcre | pcre-dl | pcre-8.44 |
zlib | zlib | zlib-dl | zlib-1.2.11 |
openssl | openssl | openssl-dl | openssl-1.1.1j |
同样,下载+解压缩:
1 | wget https://ftp.pcre.org/pub/pcre/pcre-8.44.tar.gz |
下载 nginx 源码
请根据您的 nginx 版本,选择对应版本的源码进行下载,跨越版本会导致插件无法正常工作,可能会需要您重新编译;当然如果您的 nginx 版本太过拉跨的话,不如就趁此机会顺带升级一下吧 (雾)
例如我使用的是 nginx/1.19.7
,您可以使用 nginx -v 指令查询您的 nginx 版本。
名称 | 官网地址 | 下载地址 | 截稿时的最新软件包 |
---|---|---|---|
nginx | nginx | nginx-dl | nginx-1.19.7 |
下载完成,解压备用
1 | wget https://nginx.org/download/nginx-1.19.7.tar.gz |
下载 ngx_http_geoip2_module
这个模块就是用来让 nginx 读取 MaxMind GeoIP2 数据库的模块。
1 | git clone https://github.com/leev/ngx_http_geoip2_module.git |
如果没有安装 git ,也可以下载 Release 包使用:
1 | wget https://github.com/leev/ngx_http_geoip2_module/archive/3.3.tar.gz |
开始编译
编译使用的应该是 gcc 编译器,并且会使用到 make 相关的工具,我使用的系统中已经提供了这些工具,因而没有出现报错;如果您的系统在编译的过程中出现报错,那么可能是您缺少对应的工具,您可以自行搜索。
进入 nginx 源码目录
1 | cd nginx-1.19.7/ |
配置构建参数
1 | ./configure \ |
请注意,如果使用的是不是 git clone
的方式获取 ngx_http_geoip2_module ,您可能需要修改目录的位置为 ngx_http_geoip2_module-3.3
(以3.3版本为例)
ngx_http_geoip2_module 里 ReadMe.md 的方法是错误的,不附带 --with-compat
参数会让构建出来的模块无法被使用。
而如果您安装的 nginx 默认参数不带有 --with-compat
(可以使用 nginx -V | grep with-compat
查询) ,那么您可能需要完成重新编译了。(非常感谢 @ADD-SP 的提醒!)
构建完成后,您应当可以看见如下的输出:
1 | Configuration summary |
构建模块
构建时候单纯构建模块就足够了,完整构建浪费资源和时间。
1 | make modules |
构建完成后您可以看见类似如下的输出:
1 | objs/addon/ngx_http_geoip2_module/ngx_http_geoip2_module.o \ |
到此,模块就已经编译完成,可以准备动态加载了。
加载模块
建立动态模块目录
构建完成的模块在 objs/
目录下,为了避免后续清理工作目录的操作可能会导致误删,此处建议将这些模块移动到一个比较安全的地方,例如 /etc/nginx
中。为了和静态模块 modules
区分,我们新建一个 dynamic-modules
目录。
1 | mkdir /etc/nginx/dynamic-modules |
然后就可以快乐地迁移模块啦。
1 | mv objs/*.so /etc/nginx/dynamic-modules/ |
编写模块加载配置
出于管理上的方便考虑,我们可以在 /etc/nginx
下新建一个模块配置文件 (如 modules.conf
),专门用于模块的加载管理,其中写入我们的模块加载语句:
1 | # Maxmind GeoIP2 |
并在 nginx.conf
中加载这个配置文件:
1 | user nginx; |
这样就能完成模块的加载啦。
编写模块调用配置
光有模块加载还不足够,还需要让模块中的数据能为我们所用。而方法其实也很简单,以国家码为例,在 http / stream 块中按照如下的方式配置即可:
1 | geoip2 /path/to/your/GeoLite2-Country.mmdb { |
$geoip2_country_code
会被设置成 ISO 3166 规定的国家码。
详细的使用规则可以参见 模块的使用样例 ,此处不再赘述。
编写工作规则
获得了请求地址的国家地区码后,就可以进行匹配了。例如对于加速站设置一条优化,将所有非中国的访客全部禁止访问:
1 | ## Country Restrict |
以避免其他请求消耗加速站的流量吧。毕竟在现代世界,使用 CloudFlare 获得的体验比直连好上不少呀。