场景:
因防火墙到期,原网站接入的需要回到公网的解析,经过分析,站点只需要国内访问。于是想到了用地址过滤,目前比较火的是nginx的allow和deny,另外一种是geoip,geoip2
区别:
GeoIP用于通过IP获取地理位置信息,但精度有限,更适用于大致定位。
GeoIP已经发展到GeoIP2,文件格式从.dat变为.mmdb。
MaxMind提供免费的GeoLite数据库,但已经停止更新GeoIP格式(.dat),只维护GeoIP2格式(.mmdb)。
GeoIP可以动态加载到Nginx等软件,GeoIP2需要重新编译。
GeoLite2是GeoIP2的免费版本,准确性较差,每周更新一次。
从2019年开始,GeoLite2数据库需要注册账户和License Key才能下载。
GeoIP的优点是可以动态加载到软件中,而GeoIP2需要重新编译。
需要的软件:
Nginx+GeoIP2:
nginx-1.22.0.tar.gz
libmaxminddb-1.6.0.tar.gz
ngx_http_geoip2_module-3.4.tar.gz
GeoLite2-City_20220802.tar.gz
GeoLite2-Country_20220802.tar.gz
=====
好的,把安装libmaxminddb库和编译Nginx with GeoIP2模块的两个脚本合并起来,注意顺序如下:
#!/bin/bash
# 安装libmaxminddb依赖
wget -c https://github.com/maxmind/libmaxminddb/releases/download/1.6.0/libmaxminddb-1.6.0.tar.gz
tar -zxvf libmaxminddb-1.6.0.tar.gz
cd libmaxminddb-1.6.0
./configure
make && make install
# 配置动态库目录
tee -a /etc/ld.so.conf.d/libc.conf <<EOF
/usr/local/lib
EOF
ldconfig
# 创建Nginx目录
mkdir /data/app/nginx -p
# 安装Nginx依赖
yum install gcc zlib-devel pcre-devel openssl-devel -y
# 下载和解压
wget http://nginx.org/download/nginx-1.22.0.tar.gz
tar xf nginx-1.22.0.tar.gz
# 下载和解压GeoIP2模块
wget -c https://github.com/leev/ngx_http_geoip2_module/archive/refs/tags/3.4.tar.gz -O ngx_http_geoip2_module-3.4.tar.gz
tar -zxf ngx_http_geoip2_module-3.4.tar.gz
# 编译配置
cd nginx-1.22.0/
./configure --with-http_ssl_module --add-module=../ngx_http_geoip2_module-3.4
# 编译、安装
make && make install
# 设置PATH
export PATH=/data/app/nginx/sbin:$PATH
# 检查并启动
/data/app/nginx/sbin/nginx -t
/data/app/nginx/sbin/nginx
# 检查是否启动
netstat -nltp | grep nginx
主要注意点:
-
首先安装libmaxminddb库依赖
-
再编译包含GeoIP模块的Nginx
-
Nginx编译需要GCC和相关开发库
-
设置PATH并启动Nginx
================
如果Nginx已经部署运行,只需要新增GeoIP模块,可以只重新编译并替换nginx二进制文件,无需完全重新安装。
具体操作步骤可以是:
-
备份当前运行的nginx二进制文件,例如 mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak
-
下载Nginx源码,解压到指定目录
-
配置时只添加GeoIP模块,例如:–add-module=ngx_http_geoip2_module-3.4
-
编译生成的nginx二进制文件会在nginx源码的objs目录下
-
拷贝objs/nginx到现有nginx的sbin目录下,覆盖原有二进制
-
重新加载nginx,加载新的模块
-
用nginx -V 确认模块加载成功
这种方式可以避免重复编译其他模块以及完全重新安装配置。只需要替换新增模块的二进制文件即可轻松实现模块热加载。
=============================================================
下载对应的数据库文件:
https://www.maxmind.com/en/accounts/902941/geoip/downloads
下载好之后,测试下
mmdblookup --file /usr/local/GeoIP2/GeoLite2-Country.mmdb --ip 8.8.8.8
验证GeoIP模块部署环境,我们需要针对nginx相关配置文件进行如下配置
1.在 nginx.conf 中进行如下几个关键部分配置。
load_module modules/ngx_http_geoip2_module.so;
user deploy;
worker_processes 4;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
geoip2 /usr/local/GeoIP2/GeoLite2-Country.mmdb {
$geoip2_country_code country names en;
$geoip2_data_country_code country iso_code; # CN
$geoip2_data_country "default=中国" source=$remote_addr country names zh-CN; # 中国
$geoip2_data_country_continent continent names zh-CN; # 亚洲
}
map $geoip2_data_country_code $allowed_country {
default no;
CN yes;
}
# 定义新的日志格式geo_access,包含原有访问信息和GeoIP信息
log_format geo_access '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $http_x_forwarded_for $request_time '
'$upstream_response_time $upstream_addr $http_host '
'$geoip2_data_country_code';
access_log logs/access.log geo_access;
变量要对应的上,server模块
server {
listen 80;
listen 443 ssl;
server_name ban.test.com;
#证书
#ssl on;
ssl_certificate /data/app/nginx/conf/ssl/server.pem;
ssl_certificate_key /data/app/nginx/conf/ssl/server.key;
access_log logs/host.access.log geo_access;
location / {
if ($allowed_country = no) {
return 403;
}
}
}
日志打印:
tips: 范例
geoip2 /etc/maxmind/GeoLite2-Country.mmdb {
$geoip2_data_country_code country iso_code;
}
server {
if ($geoip2_data_country_code = CN) {
rewrite ^ http://cn.example.com$request_uri?;
}
if ($geoip2_data_country_code = US) {
rewrite ^ http://us.example.com$request_uri?;
}
location / {
proxy_pass http://default.example.com;
}
}
server {
...
location / {
#本地网段白名单
if ($allow-ip = yes ) {
set $allowed_country yes;
}
#国家地区白名单
if ($allowed_country = no) {
return 403;
}
#指定国家跳转到指定域名
if ($geoip2_data_country_code = CN) {
return 301 https://www.domain.cn$request_uri;
}
}
...
}
#允许本地网段访问
geo $allow-ip{
default no;
192.168.10.0/24
港澳台地区:
map $geoip2_data_country_code $CN {
CN yes;
TW yes;
HK yes;
MO yes;
default no;
}
达到效果了,国内访问200.国外访问403,city模块也可以使用,具体的暂时还未用到。
总结:要修改日志格式,以及nginx的版本和模块的版本不要相差太远