隐藏

实现分流或屏蔽某个地区访问解决方案是在Nginx安装GeoIP模块

发布:2022/12/21 11:00:29作者:管理员 来源:本站 浏览次数:787

有时候我们想屏蔽某个地区的 IP 访问,或者根据访问来源转向不同的子站实现分流,此时如果用防火墙规则把 IP 重定向到预定页面并不是特别灵活的办法,特别是一个 IP 上拥有运行多个站点的情况下,正统的办法应该是用 GeoIP 配合对应的 web 服务器模块来实现需求,比如:Apache + Mod_GeoIp 或者 Nginx + Http_GeoIp_Module 等。


以下以 Nginx + GeoIP 为例,已预装 Nginx,基于宝塔。


一、安装运行库

GeoIP 基于 MaxMind GeoIp 产品,需要先安装相应运行库:


# yum install epel-release -y


# yum install geoip-devel -y

Ubuntu:apt-get install libgeoip-dev


二、重新编译

Nginx 已经预装,通过 nginx -V 查看之前的编译参数:


# nginx version: nginx/1.10.3


......


configure arguments: --user=www --group=www --prefix=/www/server/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_gzip_static_module --with-stream --with-stream_ssl_module --with-ipv6 --with-http_sub_module --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --add-module=/www/server/nginx/src/src/incubator-pagespeed-ngx-1.13.35.2-stable --add-module=/www/server/nginx/src/src/ngx_brotli

要启用 GeoIP 模块只需要在编译参数后面加上 --with-http_geoip_module 即可


# cd /www/server/nginx/src/


# ./configure --user=www --group=www --prefix=/www/server/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_gzip_static_module --with-stream --with-stream_ssl_module --with-ipv6 --with-http_sub_module --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --add-module=/www/server/nginx/src/src/incubator-pagespeed-ngx-1.13.35.2-stable --add-module=/www/server/nginx/src/src/ngx_brotli --with-http_geoip_module


# service nginx stop


# make && make install


# service nginx start

要验证是否成功启用模块,可以使用如下命令:


# ldd /www/server/nginx/sbin/nginx


......


  libGeoIP.so.1 => /lib64/libGeoIP.so.1 (0x00007f9f080d9000)


......

有显示如上字样说明安装成功。


三、修改配置

模块安装成功后,还要在 Nginx 里指定数据库,在安装运行库时默认安装了两个,位于 /usr/share/GeoIP/ 目录下,一个只有 IPv4,一个包含 IPv4 和 IPv6:


# ls /usr/share/GeoIP/


GeoIP.dat  GeoIP-initial.dat  GeoIPv6.dat  GeoIPv6-initial.dat

找到数据库文件后,就要修改 nginx 配置,在 http 段增加:


# vim /www/server/nginx/conf/nginx.conf


......


# 配置一个即可;


    geoip_country /usr/share/GeoIP/GeoIP.dat;


#     geoip_city /usr/share/GeoIP/GeoLiteCityv6.dat;


......


# nginx -t


nginx: the configuration file /www/server/nginx/conf/nginx.conf syntax is ok


nginx: configuration file /www/server/nginx/conf/nginx.conf test is successful


# service nginx reload


Reload service nginx...  done

由于 IP 广播泛滥,所以 GeoIP 并不是那么准确,如果觉得 GeoIP 库太旧了,可以自行到官网下载最新版,将上述配置的路径改一下即可。


GeoIP:仅 IPv4 国家

GeoIPv6:仅 IPv4+IPv6 国家

GeoLiteCity:IPv4 国家 + 省份 + 城市

GeoLiteCityIpv6:IPv4 及 IPv6 国家 + 省份 + 城市

GeoIP 官方下载页 、GeoIP2 官方下载页

四、使用方法

GeoIP 参数

使用 GeoIP 数据库

$geoip_country_code; - 国家名的前两个字母, 如, "RU", "US";

$geoip_country_code3; - 国家名的前三个字母, 如, "RUS", "USA";

$geoip_country_name; - 国家名称, 如, "Russian Federation", "United States";


使用 GeoLiteCity 数据库

$geoip_city_country_code; -国家名的前两个字母, 如, "RU", "US";

$geoip_city_country_code3; - 国家名的前三个字母, 如, "RUS", "USA";

$geoip_city_country_name; -国家名称, 如, "Russian Federation", "United States";

$geoip_region; - 省,州或区名 (province, region, state, province, federal land, and the like), 如, "Moscow City", "DC";

$geoip_city; - 城市名称, 如, "Moscow", "Washington";

$geoip_postal_code; - 邮政编号;


使用示例

屏蔽国家

使用 GeoIP 数据库


# vim /www/server/nginx/conf/vhost/test.conf


......


location / {


default_type text/html;


charset utf-8;


if ( $geoip_country_code = CN ) {


return 502 "无权访问!";


}


}


......

注:注意空格,少了会报错。


屏蔽城市

使用 GeoLiteCity 数据库


# vim /www/server/nginx/conf/vhost/test.conf


......


location / {


default_type text/html;


charset utf-8;


if ( $geoip_city = Beijing ) {


return 502 "无权访问!";


}


}


......

注:城市列表可参考官方 CSV 文档。


屏蔽省份

使用 GeoLiteCity 数据库


# vim /www/server/nginx/conf/vhost/test.conf


......


location / {


default_type text/html;


charset utf-8;


if ( $geoip_region = 22 ) {


return 502 "无权访问!";


}


}


......

注:实际测试发现屏蔽省份不能使用说明中的 Beijing、Guangdong 等字眼,需要使用 ISO 3166 规定的代码,代码参见:官方 CSV 文档。

但与此同时又产生一个让人不解的问题,二位数字代码不是唯一的,比如本例中的 22,既可表示 Beijing,又可表示 Goycay,GeoIP 如何保证对应呢?


参考文章:

1、《HttpGeoIP - 中文文档》

2、《Nginx增加GeoIP模块实现屏蔽某个国家的IP访问》

3、《Debian/Ubuntu下安装GeoIP》