ifconfig.me 访问ifconfig.me会返回客户端的IP地址(其返回结果本身就没有换行符)
1 2 wsl2-gentoo ~ 2407:8207:1930:1600:4df2:5cd1:c2b7:f8adwsl2-gentoo ~
原生版 如果只是单纯返回客户端 IP 地址,Nginx 简单配置即可,例如
1 2 3 4 5 6 7 8 9 10 server { listen 80; server_name myip.wafcloud.cn; access_log /var/log /nginx/myip.wafcloud.cn.log; location / { default_type text/plain; return 200 $remote_addr \r\n; } }
效果如下
1 2 3 wsl2-gentoo ~ # curl myip.wafcloud.cn 22.11.15.145 wsl2-gentoo ~ #
增强版 除返回客户端 IP 地址外,还包括 IP 地址的地域属性、ASN、所属机构等(取决于你所选择的 IP 地址库及封装效果)。
本实现是通过 Nginx 模块实现,不需要任何编码。
考虑到个人需求、 IP 地址库精确度及更新频率等,这里选择三个地址库,来源于两个站点:
前期准备 相关软件下载及依赖安装
依赖安装(database/C library)
1 2 3 4 5 6 7 8 9 apt install libmaxminddb0 wget https://github.com/chrislim2888/IP2Location-C-Library/archive/refs/tags/8.6.1.tar.gz tar xvf 8.6.1.tar.gz cd IP2Location-C-Library-8.6.1autoreconf -i -v --force ./configure make make install
下载并解压
1 2 3 4 5 6 7 wget https://nginx.org/download/nginx-1.24.0.tar.gz wget https://www.openssl.org/source /openssl-3.2.1.tar.gz wget https://www.zlib.net/zlib-1.3.1.tar.gz wget https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.42/pcre2-10.42.tar.gz wget https://github.com/leev/ngx_http_geoip2_module/archive/refs/tags/3.4.tar.gz wget https://github.com/ip2location/ip2location-nginx/archive/refs/tags/8.6.0.tar.gz
Nginx 及模块编译、安装(根据实际情况处理依赖、路径等问题)
1 2 3 4 5 6 7 8 9 10 ./configure --sbin-path=/usr/local /nginx/nginx \ --conf-path=/usr/local /nginx/nginx.conf \ --pid-path=/usr/local /nginx/nginx.pid \ --with-pcre=../pcre2-10.42 \ --with-zlib=../zlib-1.3.1 \ --with-http_ssl_module \ --with-openssl=../openssl-3.2.1\ --with-stream \ --add-dynamic-module=../ngx_http_geoip2_module-3.4 \ --add-dynamic-module=../ip2location-nginx-8.6.0
1 make -j`nproc` && make install
nginx.conf 关键配置(IP 库的路径按需调整)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 load_module modules/ngx_http_geoip2_module.so; load_module modules/ngx_http_ip2location_module.so; http { geoip2 /opt/data/GeoLite2-City.mmdb { $geoip2_country default="none" country names zh-CN; $geoip2_province default="none" city names zh-CN; $geoip2_city default="none" subdivisions 0 names zh-CN; } geoip2 /opt/data/GeoLite2-ASN.mmdb { $geoip2_asn default="none" autonomous_system_number; $geoip2_organization default="none" autonomous_system_organization; } ip2location_proxy_recursive on; ip2location_proxy 0.0.0.0/0; ip2location_database /opt/data/IP2LOCATION-LITE-DB3.IPV6.BIN; server { listen 80; server_name myip.wafcloud.cn; charset utf-8; access_log logs/myip.wafcloud.cn.log main; location / { default_type text/plain; return 200 "\n数据源: GeoLite2-City.mmdb\nIP: $remote_addr \nCountry: $geoip2_country \nProvince: $geoip2_province \nCity: $geoip2_city \nASN: $geoip2_asn \nOrganization: $geoip2_organization \n\n-------\n\n数据源: IP2LOCATION-LITE-DB3.IPV6.BIN\nIP: $remote_addr \nCountry: $ip2location_country_long \nRegion: $ip2location_region \nCity: $ip2location_city \n\n" ; } } }
实现的效果(IP 地址进行了脱敏,并不是 IP 库精度问题)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 wsl2-gentoo ~ 数据源: GeoLite2-City.mmdb IP: 22.11.15.145 Country: 中国 Province: 北京 City: 北京市 ASN: 4808 Organization: China Unicom Beijing Province Network ------- 数据源: IP2LOCATION-LITE-DB3.IPV6.BIN IP: 22.11.15.145 Country: China Region: Beijing City: Beijing
更进一步,可查询指定 IP 的信息 只实现了 geoip2 的查询;ip2location 应该需要改源码(???)暂未实现. update: 已实现,参考最后patch
nginx.conf 的关键配置如下:geoip2 支持 source 参数,然后通过 map 指令映射待查询的 IP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 http { map $uri $query_addr { default $remote_addr ; "~*/ipinfo/(.*)" $1 ; } geoip2 /opt/data/GeoLite2-City.mmdb { $geoip2_country default="none" source =$query_addr country names zh-CN; $geoip2_province default="none" source =$query_addr city names zh-CN; $geoip2_city default="none" source =$query_addr subdivisions 0 names zh-CN; } geoip2 /opt/data/GeoLite2-ASN.mmdb { $geoip2_asn default="none" source =$query_addr autonomous_system_number; $geoip2_organization default="none" source =$query_addr autonomous_system_organization; } ip2location_proxy_recursive on; ip2location_proxy 0.0.0.0/0; ip2location_database /opt/data/IP2LOCATION-LITE-DB3.IPV6.BIN; server { listen 80; server_name myip.wafcloud.cn; location ~* /ipinfo/(.*) { default_type text/plain; return 200 " 数据源: GeoLite2-City.mmdb IP: $query_addr Country: $geoip2_country Province: $geoip2_province City: $geoip2_city ASN: $geoip2_asn Organization: $geoip2_organization 数据源: IP2LOCATION-LITE-DB3.IPV6.BIN IP: $query_addr Country: $ip2location_country_long Region: $ip2location_region City: $ip2location_city \n\n" ; } } }
实现的效果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 wsl2-gentoo ~ 数据源: GeoLite2-City.mmdb IP: 87.114.196.191 Country: United Kingdom Province: Whitechapel City: "none" ASN: 20473 Organization: AS-VULTR 数据源: IP2LOCATION-LITE-DB3.IPV6.BIN IP: 87.114.196.191 Country: United Kingdom of Great Britain and Northern Ireland Region: England City: London
IP 地址库更新 官方有提供相关的自动更新工具,个人更倾向于自行封装脚本按需更新
其它 结合 IP 地址库可以做很多事情,比如限制特定国家的访问、基于访客地域的特定推广等,当然这种环境建议购买商业库而非使用免费版。
ip2location-nginx-8.6.0.patch 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 diff --git a/ngx_http_ip2location_module.c b/ngx_http_ip2location_module.c index 3ccb710..02f0dba 100644 @@ -370,7 +370,21 @@ ngx_http_ip2location_get_records(ngx_http_request_t *r) ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "IP address detected by IP2Location: %s", p); - return IP2Location_get_all(gcf->handler, (char *)p); + //return IP2Location_get_all(gcf->handler, (char *)p); + u_char iparam[NGX_INET6_ADDRSTRLEN + 1]; + ngx_http_variable_value_t* val; + ngx_str_t name = ngx_string("query_addr"); + iparam[0]='\0'; + val = ngx_http_get_variable(r, &name, ngx_hash_key(name.data, name.len)); + if( val && !val->not_found && val->valid){ + memcpy(iparam, val->data, val->len); + iparam[val->len]='\0'; + } + if(iparam[0]!='\0'){ + return IP2Location_get_all(gcf->handler, (char *)iparam); + } else { + return IP2Location_get_all(gcf->handler, (char *)p); + } } return NULL;