Nginx根据IP的国家、城市、ASN访问控制

由于网络安全方面的需要,网站经常会被海外的一些IP扫描和CC攻击,通常攻击者都是使用海外廉洁IDC服务商的VPS进行的,常见如:微软云,亚马逊,Vultr。当发现大量请求导致CPU占满的情况时,可以查看Nginx访问日志,集中屏蔽掉 机房/地域 的IP访问。端口层面可以使用 iptables 拉黑IP段方式,这里主要是应用/网站层面 进行IP、地域的判断,如果配合 Lua 还可以实现更多逻辑。

环境
NGINX
IP数据库

IP数据库下载地址:https://www.maxmind.com 登录后可以免费下载开源的数据库,效果还是很不错的。

GeoLite2-ASN.mmdb
GeoLite2-City.mmdb
GeoLite2-Country.mmdb

ASN相当于IP的品牌号码,可用来鉴别各个机房的IP,查询对应IDC机房的ASN可以到该网站:http://bgp.he.net

libmaxminddb
yum -y install libmaxminddb-devel

测试工具
mmdblookup --file GeoLite2-Country.mmdb --ip=123.123.123.123

ngx_http_geoip2_module
cd /
git clone https://github.com/leev/ngx_http_geoip2_module
cd /www/server/nginx/src

宝塔的Nginx源码目录 /www/server/nginx/src

nginx -V
nginx 编译信息

nginx version: nginx/1.18.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
built with OpenSSL 1.1.1g  21 Apr 2020
TLS SNI support enabled
configure arguments: --user=www --group=www --prefix=/www/server/nginx --add-module=/www/server/nginx/src/ngx_devel_kit --add-module=/www/server/nginx/src/lua_nginx_module --add-module=/www/server/nginx/src/ngx_cache_purge --add-module=/www/server/nginx/src/nginx-sticky-module --with-openssl=/www/server/nginx/src/openssl --with-pcre=pcre-8.43 --with-http_v2_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_stub_status_module --with-http_ssl_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_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 --with-cc-opt=-Wno-error --with-ld-opt=-ljemalloc --with-http_dav_module --add-module=/www/server/nginx/src/nginx-dav-ext-module
复制 configure arguments:后面的全部内容,再最后面加上
--add-dynamic-module=/ngx_http_geoip2_module
./configure --user=www --group=www --prefix=/www/server/nginx --add-module=/www/server/nginx/src/ngx_devel_kit --add-module=/www/server/nginx/src/lua_nginx_module --add-module=/www/server/nginx/src/ngx_cache_purge --add-module=/www/server/nginx/src/nginx-sticky-module --with-openssl=/www/server/nginx/src/openssl --with-pcre=pcre-8.43 --with-http_v2_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_stub_status_module --with-http_ssl_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_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 --with-cc-opt=-Wno-error --with-ld-opt=-ljemalloc --with-http_dav_module --add-module=/www/server/nginx/src/nginx-dav-ext-module --add-dynamic-module=/ngx_http_geoip2_module

重新编译
make
objs 目录下面得到编译好的 ngx_http_geoip2_module.so

nginx.conf

load_module /modules/ngx_http_geoip2_module.so;
http
{
        geoip2 /www/ipdb/GeoLite2-Country.mmdb {
          auto_reload 60m;
          $geoip2_metadata_country_build metadata build_epoch;
          $geoip2_data_country_code default=CN source=$remote_addr country iso_code;
          $geoip2_data_country_name country names en;
        }
        geoip2 /www/ipdb/GeoLite2-City.mmdb {
          $geoip2_data_city_name default=null city names en;
        }
        geoip2 /www/ipdb/GeoLite2-ASN.mmdb {
          $geoip2_data_asn_code default=0 autonomous_system_number;
          $geoip2_data_asn_name default=null autonomous_system_organization;
        }
    #......省略
}
默认是使用 $remote_addr ,一般反向代理是 X-Forwarded-For ,CF 是
CF-Connecting-IP,需要自定义 使用 source=$remote_addr 设置。

测试

location /ip
{
  default_type    text/html;
  return 200 '$geoip2_data_country_code $geoip2_data_country_name  $geoip2_data_city_name  $geoip2_data_asn_name $geoip2_data_asn_code';
}
location /
{
    if ($geoip2_data_country_name = "Japan") {
        return 444;
    }
    #....省略
}
 

$geoip2_data_country_name country names en

mmdblookup --file GeoLite2-Country.mmdb --ip=123.123.123.123
 

{
   country:{
       names:{
          en:"US"
       }
    }
}
 
Last modification:May 15th, 2022 at 09:53 am

Leave a Comment