使用场景
过滤指定地区/国家的IP,一般是国外IP禁止请求。
使用geoip模块实现不同国家的请求被转发到不同国家的nginx服务器,也就是根据国家负载均衡。
前置知识
GeoIP是什么?
官网地址
https://www.maxmind.com/en/home
包含IP地址的地理位置的数据库。
分为收费版本和免费版本
收费版本为GeoIP2,免费版本为GeoIPlite
nginx plus版本,也就是收费版的配置较为简单,geoip库已经被内置到yum仓库中。
nginx开源版本则没有。
实现
下载geoip模块
最新的release中作者说支持1.20版本,实测nginx1.24版本也支持
https://github.com/leev/ngx_http_geoip2_module
配置编译nginx的依赖。
我的做法是先配置nginx的官方源,
yum安装最新版stable的nginx,
nginx -V
获取默认的编译参数,
然后再下载nginx对应版本的源码包进行编译替换nginx二进制文件即可。
下载geo模块到指定目录,解压,编译参数指定即可
./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_geoip_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --add-dynamic-module=/opt/nginx/geo/ngx_http_geoip2_module-3.4 --with-cc-opt='-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'
注意参数--add-dynamic-module=/opt/nginx/geo/ngx_http_geoip2_module-3.4
之后执行make
编译命令,编译之后nginx二进制文件会在源码包的objs
目录中,验证是否编译成功
[root@localhost nginx-1.24.0]# cd objs/
[root@localhost nginx-1.24.0]# ./nginx -V
nginx version: nginx/1.24.0
built by gcc 8.5.0 20210514 (Red Hat 8.5.0-4) (GCC)
built with OpenSSL 1.1.1k FIPS 25 Mar 2021
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_geoip_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --add-dynamic-module=/opt/nginx/geo/ngx_http_geoip2_module-3.4 --with-cc-opt='-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'
替换掉原来的nginx文件,nginx支持不停机升级,我这里由于没有服务在运行,就直接停机替换文件升级了。
# 找到nginx的执行路径
whereis nginx
cp 备份
cp ./objs/nginx 到原有执行路径
配置文件编写
load_module /opt/nginx/nginx-1.24.0/objs/ngx_http_geoip2_module.so;# 以下内容位于http模块中server_tokens off;charset utf-8;log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"''"$geoip2_country_code" $geoip2_country_name_cn'; # 日志中显示访问国家代码,地区,要配置日志中显示中文才能看到。access_log /var/log/nginx/access.log main;sendfile on;tcp_nopush on;tcp_nodelay on;real_ip_header X-Forwarded-For;map $http_x_forwarded_for $realip {~^(\d+\.\d+\.\d+\.\d+) $1;default $remote_addr;}geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb { # 加载模块$geoip2_country_code source=$realip country iso_code;$geoip2_country_name_en source=$realip country names en;$geoip2_country_name_cn source=$realip country names zh-CN;}
这里如果你参考nginx社区版的官方文档会发现语法不同,而且指定的数据库文件也不同,一个是mmdb,一个是dat。
https://nginx.org/en/docs/http/ngx_http_geoip_module.html
实例
实例:禁止非中国的IP地址访问->禁止国家代码不是CN的访问
location / {if ($geoip2_country_code != CN ){return 404;}}
测试是可以生效的。具体测试方法不再说明。
其他
编译完geoip2模块之后,在objs目录中还存在ngx_stream_geoip2_module.so
模块。
可以利用此模块实现根据不同国家代码转发到不同国家的服务,实现基于IP地址地理位置的负载均衡。
备注:此方法未试验过。
参考
https://docs.nginx.com/nginx/admin-guide/dynamic-modules/geoip/
https://blog.csdn.net/guyan0319/article/details/78845159