玩下Nginx的GeoIp
Nginx使用版本:1.27.2,构建环境:RockyLinux9
一些基础软件包
这里可能会包含其他模块的,懒得分出来了~
dnf一些配置就自行GPT吧,懒得分解了~
dnf --setopt=fastestmirror=True --setopt=deltarpm=True --setopt=max_parallel_downloads=10 --setopt=keepcache=True makecache
dnf -y update
dnf -y in epel-release
dnf -y groupinstall 'Development Tools'
dnf -y in nano wget psmisc cmake go automake gcc gcc-c++ kernel-devel git make tar autoconf \
zlib zlib-devel openssl openssl-devel bzip2 bzip2-devel pcre pcre-devel perl-IPC-Cmd libaio libaio-devel \
brotli-devel glibc-headers glibc-devel libbsd-devel perl-core libxcrypt-compat libtool binutils binutils-gold
dnf clean all
编译构建
直接原仓库拉最新的,个人喜好~
这里只会展示Geo
需要的模块
-j$(nproc)
会自动根据cpu
获取执行线程数,快是会快设备都会短暂卡顿,所以建议上构建机去构建
- 拉取
libmaxminddb
git clone --depth 1 --recurse-submodules https://github.com/maxmind/libmaxminddb.git libmaxminddb
cd libmaxminddb && ./bootstrap && ./configure
make -j$(nproc) && make install && make clean
- 拉取
ngx_http_geoip2_module
git clone --depth 1 --recurse-submodules https://github.com/leev/ngx_http_geoip2_module.git ngx_http_geoip2_module
nginx
的configure
configure
加上geoip2
的动态模块即可
nginx位置:objs/nginx
geoip2位置:objs/ngx_http_geoip2_module.so
--add-dynamic-module=ngx_http_geoip2_module
- 检查
nginx
检查无问题之后可直接复制到生产机器
记得加上运行权限chmod +x nginx
objs/nginx -V
nginx version: nginx/1.27.2
built by gcc 11.4.1 20231218 (Red Hat 11.4.1-3) (GCC)
built with OpenSSL 3.1.7+quic 3 Sep 2024
TLS SNI support enabled
configure arguments: --prefix=/home/nginx --with-compat --with-threads --with-file-aio --with-http_v2_module --with-http_v3_module --with-http_ssl_module --with-http_sub_module --with-http_slice_module --with-http_realip_module --with-http_degradation_module --with-http_stub_status_module --with-pcre-jit --with-pcre=../pcre2 --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-openssl=../openssl --add-module=../ngx_zstd --add-module=../ngx_brotli --add-dynamic-module=../ngx_http_geoip2_module --with-ld-opt=-ljemalloc
- 获取
mmdb
文件
mmdb
是Geo数据库文件,没有这个geoip2
无法工作
这里准备了一份脚本可自动下载,至于文件覆盖和动态更新自行增加即可
GeoLite2来源maxmind.com
,可自行注册生成LICENSE_KEY
GeoCN来源仓库
#!/bin/sh
# 检查是否提供了 LICENSE_KEY
if [ -z "$LICENSE_KEY" ]; then
echo "错误:未设置LICENSE_KEY。请将其导出为环境变量。"
exit 1
fi
# 设置 MaxMind 的下载地址
BASE_URL="https://download.maxmind.com/app/geoip_download"
echo "下载 GeoLite2-ASN.mmdb..."
curl -L -o "GeoLite2-ASN.mmdb.tar.gz" \
"${BASE_URL}?edition_id=GeoLite2-ASN&license_key=${LICENSE_KEY}&suffix=tar.gz"
if [ $? -eq 0 ]; then
tar -xvzf GeoLite2-ASN.mmdb.tar.gz --strip-components=1 && rm GeoLite2-ASN.mmdb.tar.gz
echo "GeoLite2-ASN.mmdb 已成功下载并提取。"
else
echo "GeoLite2-ASN.mmdb 下载失败。"
exit 1
fi
echo "下载 GeoLite2-City.mmdb..."
curl -L -o "GeoLite2-City.mmdb.tar.gz" \
"${BASE_URL}?edition_id=GeoLite2-City&license_key=${LICENSE_KEY}&suffix=tar.gz"
if [ $? -eq 0 ]; then
tar -xvzf GeoLite2-City.mmdb.tar.gz --strip-components=1 && rm GeoLite2-City.mmdb.tar.gz
echo "GeoLite2-City.mmdb 已成功下载并提取。"
else
echo "GeoLite2-City.mmdb 下载失败。"
exit 1
fi
echo "下载 GeoLite2-Country.mmdb..."
curl -L -o "GeoLite2-Country.mmdb.tar.gz" \
"${BASE_URL}?edition_id=GeoLite2-Country&license_key=${LICENSE_KEY}&suffix=tar.gz"
if [ $? -eq 0 ]; then
tar -xvzf GeoLite2-Country.mmdb.tar.gz --strip-components=1 && rm GeoLite2-Country.mmdb.tar.gz
echo "GeoLite2-Country.mmdb 已成功下载并提取。"
else
echo "GeoLite2-Country.mmdb 下载失败。"
exit 1
fi
echo "下载 GeoCN.mmdb..."
curl -L -o "GeoCN.mmdb" \
"http://github.com/ljxi/GeoCN/releases/download/Latest/GeoCN.mmdb"
if [ $? -eq 0 ]; then
echo "GeoCN.mmdb 已成功下载。"
else
echo "GeoCN.mmdb 下载失败。"
exit 1
fi
echo "所有Geo下载已完成。"
ls -lh
配置案例
这里分享下
日志
、屏蔽海外
内容,其他的可自行拓展
- 加载Geo模块
构建的时候是动态加载的,所以使用之前得加载
so
文件,在nginx.conf
父配置增加即可
so
路径自行修改即可
load_module ngx_http_geoip2_module.so;
- 加载Geo数据库
mmdb
路径自行修改即可
括号内容的配置问gpt
就行这里懒得分解了~
# 加载 GeoLite2 ASN 数据库
geoip2 GeoLite2-ASN.mmdb {
auto_reload 5m;
$geoip2_asn_number autonomous_system_number;
$geoip2_asn_organization autonomous_system_organization;
}
# 加载 GeoLite2 国家数据库
geoip2 GeoLite2-Country.mmdb {
auto_reload 5m;
$geoip2_country_code country iso_code;
$geoip2_country_name country names en;
}
# 加载 GeoLite2 城市数据库
geoip2 GeoLite2-City.mmdb {
auto_reload 5m;
$geoip2_city_name city names en;
$geoip2_postal_code postal code;
$geoip2_latitude location latitude;
$geoip2_longitude location longitude;
$geoip2_region_name subdivisions 0 names en;
}
# 加载 GeoCN CN数据库
geoip2 GeoCN.mmdb {
auto_reload 5m;
$geoip2_cn_isp isp;
$geoip2_cn_city city;
$geoip2_cn_net_type net;
$geoip2_cn_province province;
$geoip2_cn_district district;
}
- 屏蔽所有非CN的IP
需要屏蔽的
location /xxx
的大括号第一行加上即可~
$geoip2_country_code
是第2步定义的变量,需要对的上
# 检查国家代码,如果不是CN,则拒绝访问
if ($geoip2_country_code != "CN") {
return 403;
}
- 日志配置
这里转成
json
方便日志系统读取,不需要可让gpt
转一下即可~
各种$geoip2_
开头的是第2步定义的变量,需要对的上
# 将英文月份缩写映射为数字
map $month $month_num {
"Jan" "01";
"Feb" "02";
"Mar" "03";
"Apr" "04";
"May" "05";
"Jun" "06";
"Jul" "07";
"Aug" "08";
"Sep" "09";
"Oct" "10";
"Nov" "11";
"Dec" "12";
}
# 格式化时间为 yyyy-MM-dd HH:MM:SS
map $time_local $custom_time_local {
default "$time_local"; # 默认格式
"~(?<day>[0-9]{2})/(?<month>[A-Za-z]+)/(?<year>[0-9]{4}):(?<hour>[0-9]{2}):(?<minute>[0-9]{2}):(?<second>[0-9]{2})" "$year-$month_num-$day $hour:$minute:$second";
}
# JSON 日志格式,使用格式化后的时间
log_format main escape=json '{"remote_addr":"$remote_addr",'
'"remote_user":"$remote_user",'
'"time_local":"$custom_time_local",'
'"request_method":"$request_method",'
'"request":"$request",'
'"server_protocol":"$server_protocol",'
'"status":"$status",'
'"body_bytes_sent":"$body_bytes_sent",'
'"bytes_sent":"$bytes_sent",'
'"http_referer":"$http_referer",'
'"http_user_agent":"$http_user_agent",'
'"request_time":"$request_time",'
'"server_name":"$server_name",'
'"server_addr":"$server_addr",'
'"connection":"$connection",'
'"connection_requests":"$connection_requests",'
'"geoip2_country_code":"$geoip2_country_code",'
'"geoip2_country_name":"$geoip2_country_name",'
'"geoip2_city_name":"$geoip2_city_name",'
'"geoip2_region_name":"$geoip2_region_name",'
'"geoip2_postal_code":"$geoip2_postal_code",'
'"geoip2_latitude":"$geoip2_latitude",'
'"geoip2_longitude":"$geoip2_longitude",'
'"geoip2_asn_number":"$geoip2_asn_number",'
'"geoip2_asn_organization":"$geoip2_asn_organization",'
'"upstream_addr":"$upstream_addr",'
'"upstream_response_time":"$upstream_response_time",'
'"http_x_forwarded_for":"$http_x_forwarded_for"}';
# 日志位置配置
error_log logs/error.log;
access_log logs/access.log main;
- 大致效果
{
"remote_addr": "112.57.65.69",
"remote_user": "",
"time_local": "2024-10-30 11:08:32",
"request_method": "GET",
"request": "GET / HTTP/1.1",
"server_protocol": "HTTP/1.1",
"status": "301",
"body_bytes_sent": "162",
"bytes_sent": "356",
"http_referer": "",
"http_user_agent": "DNSPod-Monitor/2.0",
"request_time": "0.000",
"server_name": "xxx.xxx.com",
"server_addr": "10.0.8.14",
"connection": "151379",
"connection_requests": "1",
"geoip2_country_code": "CN",
"geoip2_country_name": "China",
"geoip2_city_name": "",
"geoip2_region_name": "",
"geoip2_postal_code": "",
"geoip2_latitude": "34.77320",
"geoip2_longitude": "113.72200",
"geoip2_asn_number": "9808",
"geoip2_asn_organization": "China Mobile Communications Group Co., Ltd.",
"upstream_addr": "",
"upstream_response_time": "",
"http_x_forwarded_for": ""
}
最后
如果对各位佬有帮助,请帮忙点个赞~
如果需要完整的nginx
配置,可查看本人仓库
如果内容有不对的地方欢迎提出,本人渴望进步~