玩下Nginx的GeoIp

玩下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获取执行线程数,快是会快设备都会短暂卡顿,所以建议上构建机去构建

  1. 拉取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
  1. 拉取ngx_http_geoip2_module
git clone --depth 1 --recurse-submodules https://github.com/leev/ngx_http_geoip2_module.git ngx_http_geoip2_module
  1. nginxconfigure

configure加上geoip2的动态模块即可
nginx位置:objs/nginx
geoip2位置:objs/ngx_http_geoip2_module.so

--add-dynamic-module=ngx_http_geoip2_module 
  1. 检查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
  1. 获取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

配置案例

这里分享下日志屏蔽海外内容,其他的可自行拓展

  1. 加载Geo模块

构建的时候是动态加载的,所以使用之前得加载so文件,在nginx.conf父配置增加即可
so路径自行修改即可

load_module ngx_http_geoip2_module.so;
  1. 加载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;
}
  1. 屏蔽所有非CN的IP

需要屏蔽的location /xxx的大括号第一行加上即可~
$geoip2_country_code是第2步定义的变量,需要对的上

# 检查国家代码,如果不是CN,则拒绝访问
if ($geoip2_country_code != "CN") {
    return 403;
}
  1. 日志配置

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

5 个赞

感谢大佬教程

感谢大佬分享