Nginx 内嵌GeoIP库

作者:matrix 发布时间:2025-06-05 分类:零零星星

图片6014-Nginx 内嵌GeoIP库

nginx可以内置IP地址解析功能,无需依赖三方 api

免费的geoip库文件下载:

https://git.io/GeoLite2-City.mmdb

优点:nginx 集成方便
缺点:依赖GeoIP库准确度,国内个别 IP 解析存在问题

构建支持geoip2模块的 Nginx

# 构建阶段
FROM nginx:latest AS builder

# Install build dependencies
RUN apt-get update && apt-get install -y \
    wget \
    git \
    gcc \
    make \
    libpcre3-dev \
    zlib1g-dev \
    libmaxminddb-dev \
    && rm -rf /var/lib/apt/lists/*

# Get nginx source code (same version as base image)
RUN wget http://nginx.org/download/nginx-$(nginx -v 2>&1 | sed 's/^.*nginx\///' | sed 's/ .*$//').tar.gz \
    && tar zxf nginx-*.tar.gz \
    && rm nginx-*.tar.gz

# Get and compile the GeoIP2 module
RUN git clone https://github.com/leev/ngx_http_geoip2_module.git

# Configure and compile Nginx with the GeoIP2 module
RUN cd nginx-$(nginx -v 2>&1 | sed 's/^.*nginx\///' | sed 's/ .*$//') \
    && ./configure --with-compat --add-dynamic-module=../ngx_http_geoip2_module \
    && make modules

# 最终镜像
FROM nginx:latest

# 只安装运行时依赖
RUN apt-get update && apt-get install -y \
    libmaxminddb0 \
    && rm -rf /var/lib/apt/lists/*

# 从构建阶段复制编译好的模块
COPY --from=builder /nginx-*/objs/ngx_http_geoip2_module.so /usr/lib/nginx/modules/

# Create directory for GeoIP2 database
RUN mkdir -p /etc/nginx/geoip && curl -Ls https://git.io/GeoLite2-City.mmdb -o /etc/nginx/geoip/GeoLite2-City.mmdb

# nginx.conf 顶部载入模块
RUN echo 'load_module modules/ngx_http_geoip2_module.so;' > /etc/nginx/nginx.conf.new && \
    cat /etc/nginx/nginx.conf >> /etc/nginx/nginx.conf.new && \
    mv /etc/nginx/nginx.conf.new /etc/nginx/nginx.conf

nginx config:
/root/test.conf

map $arg_ip $ip_to_check {
    default $arg_ip;
    "" $remote_addr;
}

# GeoIP2 配置
geoip2 /etc/nginx/geoip/GeoLite2-City.mmdb {
    # 自动重新加载时间
    # auto_reload 5m;
    auto_reload 1d; 
    # 国家信息
    $test_country_code source=$ip_to_check country iso_code;
    $test_country_name source=$ip_to_check country names en;
    $test_country_name_cn source=$ip_to_check country names zh-CN;

    # 省份/州信息 - 尝试不同的索引
    $test_subdivision_1_name source=$ip_to_check subdivisions 0 names en;
    $test_subdivision_1_code source=$ip_to_check subdivisions 0 iso_code;
    $test_subdivision_1_name_cn source=$ip_to_check subdivisions 0 names zh-CN;

    $test_subdivision_2_name source=$ip_to_check subdivisions 1 names en;
    $test_subdivision_2_code source=$ip_to_check subdivisions 1 iso_code;

    # 城市信息
    $test_city_name_en source=$ip_to_check city names en;
    $test_city_name_cn source=$ip_to_check city names zh-CN;

    # 位置信息
    $test_latitude source=$ip_to_check location latitude;
    $test_longitude source=$ip_to_check location longitude;
    $test_accuracy source=$ip_to_check location accuracy_radius;

    # 额外信息
    $test_timezone source=$ip_to_check location time_zone;
}

server {
    listen 80;
    server_name 127.0.0.1 localhost;
    index index.html index.htm index.php default.html default.htm default.php;
    root /var/www/none/;

    # 使用查询参数来测试IP,例如:/?ip=8.8.8.8
    location / {
        charset utf-8;
        default_type text/plain;
        add_header Content-Type 'text/plain; charset=utf-8';
        return 200 "
        Test IP: $ip_to_check

        === Country Info ===
        Country code: $test_country_code
        Country name (EN): $test_country_name
        Country name (CN): $test_country_name_cn

        === Region Info ===
        Province/State 1: $test_subdivision_1_name ($test_subdivision_1_code)
        Province/State 1 (CN): $test_subdivision_1_name_cn
        Province/State 2: $test_subdivision_2_name ($test_subdivision_2_code)

        === City Info ===
        City name (EN): $test_city_name_en
        City name (CN): $test_city_name_cn

        === Location Info ===
        Latitude: $test_latitude
        Longitude: $test_longitude
        Accuracy radius: $test_accuracy km
        Timezone: $test_timezone
        ";
    }
}

运行测试

# 构建 nginx 镜像
docker build . -t nginx-geoip

docker run --rm -it -v /root/test.conf:/etc/nginx/conf.d/test.conf -p 80:80  nginx-geoip 
## 指定查询IP信息
http://127.0.0.1/?ip=8.8.8.8 

## 查询当前IP信息
http://127.0.0.1

定时更新mmdb文件

可自己配置需要的 Crontab 任务执行文件更新

docker exec -i 容器名 sh -c 'set -e; curl -Ls --retry 3 --retry-delay 5 --connect-timeout 10 --max-time 60 https://git.io/GeoLite2-City.mmdb -o /tmp/geo.mmdb; \
[ -s /tmp/geo.mmdb ]; cp /etc/nginx/geoip/GeoLite2-City.mmdb /etc/nginx/geoip/GeoLite2-City.mmdb.bak; \
mv /tmp/geo.mmdb /etc/nginx/geoip/GeoLite2-City.mmdb'