跳到主要内容

Nginx 开启 GeoIP2 模块,解析源 IP 地址信息

· 阅读需 6 分钟
Mixbo

GeoIP2 module 的作用

GeoIP2 module 可以通过将 IP 地址与 MaxMind 的 GeoIP2 数据库进行匹配,为 Nginx 提供有关请求者的地理位置信息。这可以用于实现一些基于地理位置的功能,例如:

  • 根据用户所在的国家/地区为其提供不同的网站内容
  • 基于 IP 地址的访问控制,例如阻止某些国家/地区的访问
  • 基于用户地理位置的广告定向

使用 Nginx 官方 Docker image 添加 GeoIP2 模块

使用官方源 build 镜像是一种简单和可靠的方法来获取最新版本的 Nginx,同时也可以确保使用的镜像是安全的和经过官方认证的。

要使用 GeoIP2 module,需要将它添加到 Nginx 的模块列表中。可以通过构建一个自定义镜像,在其中包括 GeoIP2 module 或者通过使用预构建的镜像并添加模块作为插件进行安装。

执行以下命令从 Nginx 官网镜像 repo 重新打包 Nginx 包 参考

先在本地启动 Docker

$> cd ~/dev
$> git clone https://github.com/nginxinc/docker-nginx.git
$> cd docker-nginx/modules
# 在 modules 中通过 Dockerfile.alpine 重新打包 Nginx 并开启 geoip2 模块
$> docker build -f Dockerfile.alpine --build-arg ENABLED_MODULES="geoip2" -t nginx-with-geoip2 .

准备源数据

在配置 geoip2 之前需要到 MaxMind 下载数据,在 Nginx 中更新 GeoIP2 数据库的方法通常有以下方法:

  • 手动下载最新的 GeoIP2 数据库文件,替换旧的数据库文件即可。(需要注意的是,如果您使用的是收费版的 GeoIP2 数据库,则需要获取相应的授权以下载最新的数据库文件)
  • 除了手动下载和更新数据库文件外,还可以使用一些第三方工具自动更新 GeoIP2 数据库。可以使用 geoipupdate 工具自动从 MaxMind 网站下载并更新数据库文件。
  • 此外还有一些第三方软件或服务可以提供自动更新 GeoIP2 数据库的功能

具体操作参考官方链接

下载后的文件需要放到 /etc/nginx/modules/geoip2 目录,以方便以下配置能被正确使用

配置 geoip2 指令

在 Nginx 配置文件中,可以使用 geoip2 指令来配置 GeoIP2 module,geoip2 指令可以指定 GeoIP2 数据库文件的位置以及要查询的 IP 地址的变量名。

geoip2 modules/geoip2/GeoLite2-Country.mmdb {
auto_reload 5m;
$geoip2_metadata_country_build metadata build_epoch;
# 这里需要注意 source 位置只能在 $country_code 之后
$country_code source=$source_ip country iso_code;
$country_name country names en;
}
geoip2 modules/geoip2/GeoLite2-City.mmdb {
$geoip2_data_city_name city names en;
}

这段 Nginx 配置代码是使用 GeoIP2 module 实现 IP 地址到国家/地区和城市名称的映射,具体说明如下:

  • 定义了一个 auto_reload 指令,表示该模块将自动重新加载数据库文件并更新相关变量的值时间间隔为 5 分钟。
  • 第一个模块将请求的 IP 地址与名为 "GeoLite2-Country.mmdb" 的 MaxMind GeoIP2 国家数据库进行匹配,并指定了一个自定义的变量 $country_code$country_name。其中 $country_code 变量将返回请求者的 国家/地区 ISO3166-1 代码 ,而 $country_name 变量将返回请求者国家/地区的英文名称。 此外 $geoip2_metadata_country_build 变量将返回国家数据库的构建元数据信息即构建时间戳。
  • 第二个模块将请求的 IP 地址与名为 "GeoLite2-City.mmdb" 的 MaxMind GeoIP2 城市数据库进行匹配,并指定了一个自定义的变量 $geoip2_data_city_name, 此变量将返回请求者所在城市的英文名称。
  • 需要注意的是 $source_ip 变量没有被定义在这个 Nginx 配置中,需要在其他地方定义该变量并将其传递给这个配置块。(以下是一个获取 $source_ip 的例子,因为要走 CDN 所以要从 $proxy_add_x_forwarded_for 变量中解析获取。)
    # 从 CDN 过来的 X_FORWARDED_FOR 信息中取第一个 ip 地址当成请求的源 ip。
    # "Amazon CloudFront" "111.3.1.136, 132.116.93.159, 172.22.214.128, 172.21.201.146" -> 11.19.1.131
    # result: $source_ip = 11.19.1.131
    if ($proxy_add_x_forwarded_for ~ ^([^,]*)) {
    set $source_ip '$1';
    }
    综上,这个 Nginx 配置使用了 GeoIP2 module 和 MaxMind 的 GeoIP2 数据库,实现了 IP 地址到国家/地区和城市名称的映射,并在配置中定义了自定义变量和自动重新加载的指令。

剩下的就是正常使用 nginx-with-geoip2 这个 Nginx 镜像了