玩下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 配置,可查看本人仓库
如果内容有不对的地方欢迎提出,本人渴望进步~
|