GeoIP 简介

您所在的位置:网站首页 pokemmo地区英文的翻译是什么 GeoIP 简介

GeoIP 简介

2023-06-07 23:38| 来源: 网络整理| 查看: 265

最近接触到GeoIP ,网上查了查资料,这里记录一下,仅供学习参考

1、什么是GeoIP

  Geo是geographic的缩写,意思是地理的,GeoIP即为IP地理位置数据库,可以根据IP获得地理位置信息。GeoLite2是GeoIP2的免费版本,与GeoIP2数据库相比准确性较差。GeoLite2数据库每周更新国家、城市和自治系统编号信息,更新时间为每周二。   IP地理定位本质上是不精确的,地点通常靠近人口中心。GeoIP数据库提供的任何位置不应用于识别特定地址或家庭,使用精度半径作为IP地址返回的纬度和经度坐标的地理定位精度指示,IP地址的实际位置可能在这个半径和经纬度坐标所定义的区域内。

       GeoIP库可以根据IP地址(支持IPv4 和 IPv6), 定位该IP所在的 洲、经纬度、国家、省市、ASN 等信息。

       GeoIP目前已经升级到GeoIP2,GeoIP2有两个版本,一个免费版(GeoLite2),一个收费版本(GeoIP2, 200$起步)。

       收费版本的准确率稍高一些,更新频率为每周二更新一次, 免费版是每月第一个周二更新一次。

       两者对比可以参考官网说明 GeoIP2 City Accuracy | MaxMind

       对于大部分项目来说免费版已经足够使用了.

       除了GeoIP外, 其实还有 ip2location、Quova等也提供类似的功能, 但都是收费的.

2、用途

  因为其可以根据IP地址判断所属国家的特性,被广泛应用于各大代理软件例如Surge/Shadowrocket/Quantumult(X)/Clash中,根据设置的规则使用不同的节点服务器。   例如在Quantumult(X)中,设置以下规则:GEOIP,US,USProxyGEOIP,CN,Direct 这段规则的意思是,如果访问的IP在GeoIP数据库中的地理位置为美国(US),则使用USProxy这个策略内的服务器节点进行访问;类似的,如果是中国(CN),则使用Direct策略也就是直接连接访问。   虽然GeoIP数据库每周更新,但其中包含的youtube、google、twitter等经常访问网站IP的地理位置(指美国)并不会随之改变,所以并不需要经常更新。

3、注册使用

  此前,MaxMind一直提供GeoLite2公开的访问下载地址,但从2019年12月30日开始,MaxMind不再提供GeoLite2公开的访问下载地址,需要用户注册一个MaxMind帐户并获取许可密钥,才能下载GeoLite2数据库。   MaxMind帐户注册地址:GeoLite2 Sign Up | MaxMind直连访问,不要使用代理服务器,否则显示错误,无法注册

  注册完成后,在许可密钥界面生成许可密钥(License key),妥善保管好你的许可密钥(License key)。 GeoLite2数据库的下载地址即为:https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=此处替换为证书密钥&suffix=tar.gz

4、资源下载 4.1、公开的数据库

除了自己注册下载以外,还可以使用网络上公开的Geolite2数据库

Releases · Dreamacro/maxmind-geoip · GitHub

https://geolite.clash.dev

https://static.clash.to/GeoIP2/GeoIP2-Country.tar.gz

很多linux版本支持这个库, 可以使用yum 或 apt 进行下载, windows上使用的话就需要自己编译了.

4.2 源码下载:

Geolocate an IP address using Web Services with the client-side JavaScript | MaxMind Developer Portal

GeoIP2提供了多种语言的API接口供选择.

这里我需要使用C语言接口, 所以下载C语言版的源码.

https://github.com/maxmind/libmaxminddb/releases

4.3 GeoIP数据库下载:

https://dev.maxmind.com/geoip/geoip2/geolite2/

可以看到官网提供三种库,2种格式, 首先 官网API是需要使用二进制库文件, CSV格式的库可以导入其他程序 或 供你简单浏览。

三种库的区别可以从名字上就可以看出来:

  City       精确到城市(大小70M左右),

  Country 精确到国家(4M左右),

  ASN       用于产看IP地址的拥有者(7M左右). 需要注意的是 City 和 Country 库中不含ASN信息。

对于ASN的理解可以通过知乎了解一下 https://www.zhihu.com/question/21024981

根据业务需求选择. 这里我们下载精确到城市的数据库文件.

https://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz

由于数据库经常更新, 官网还提供了更新的方案:

GeoIP2 Release Notes | MaxMind Developer Portal

5、接口说明

libmaxminddb - a library for working with MaxMind DB files

/* ------------------数据库的关闭与打开 * 这里 MMDB_open 的 flags 参数需要说明一下, * 目前代码实现db文件都是使用mmap()映射到内存的, * 所以flags其实设置什么都无所谓,所以默认使用 MMDB_MODE_MMAP就好. */ int MMDB_open(const char *const filename, uint32_t flags, MMDB_s *const mmdb); void MMDB_close(MMDB_s *const mmdb); /* ------------------数据搜索 * 网络字节序地址搜索API, 即传入sockaddr参数是网络字节序的地址 */ MMDB_lookup_result_s MMDB_lookup_sockaddr(MMDB_s *const mmdb, const struct sockaddr *const sockaddr, int *const mmdb_error); /* 字符串IP地址搜索API, 即传入ipstr参数的null结尾字符串,如"114.240.52.162" * 这个API其实就是调用 getaddrinfo() 将字符串转换为网络地址, * 然后再调用 MMDB_lookup_sockaddr() 实现的, * 所以不要将网络地址转成字符串,再调用这个函数, 直接使用MMDB_lookup_sockaddr() * gai_error参数 是用来返回 getaddrinfo() 错误码的. */ MMDB_lookup_result_s MMDB_lookup_string(MMDB_s *const mmdb, const char *const ipstr, int *const gai_error, int *const mmdb_error); /* ------------------从搜索到数据中提取指定数据 * 下面 3 个函数意义相同, 只不过传入参数的方法不同. * 3个函数前2个参数相同, 第一个是 搜索结果中搜到的entry,具体看例子程序 * 第二个参数是 获取数据的存放处, 剩下的参数都是搜索用的数据. * 其实这3个函数实现是层层调用的关系: * MMDB_get_value()是可变参数函数, 函数内部把 可变参数 用 va_list 封装起来, * 接着调用 MMDB_vget_value(), 这个 vget函数把所有可变参数 再分离开来, * 放到一个 字符串指针数组里面, 再把这个数组传递给 MMDB_aget_value()函数, * 最终就是 aget 函数完成搜索功能. * 所以如果考虑到性能, 那个最好直接调用 aget 函数. * 另外, 需要注意 传入的参数 最后一个必须是 NULL, 否则会导致程序崩溃 */ int MMDB_get_value(MMDB_entry_s *const start, MMDB_entry_data_s *const entry_data, ...); int MMDB_vget_value(MMDB_entry_s *const start, MMDB_entry_data_s *const entry_data, va_list va_path); int MMDB_aget_value(MMDB_entry_s *const start, MMDB_entry_data_s *const entry_data, const char *const *const path); /* ------------------从搜索到数据中提取全部数据 * 调用完MMDB_lookup_sockaddr/MMDB_lookup_string 后获取所有该IP地址相关信息 * 具体使用看官方例子, 用处不大, 主要是可以用来了解一下结果数据的组成 */ int MMDB_get_entry_data_list(MMDB_entry_s *start, MMDB_entry_data_list_s **const entry_data_list); int MMDB_dump_entry_data_list(FILE *const stream,MMDB_entry_data_list_s *const entry_data_list, int indent); void MMDB_free_entry_data_list(MMDB_entry_data_list_s *const entry_data_list); int MMDB_get_metadata_as_entry_data_list(MMDB_s *const mmdb, MMDB_entry_data_list_s **const entry_data_list); /* ------------------其他, MMDB_read_node例子可以看源码的 read_node_t.c,个人觉得没什么用 */ const char *MMDB_strerror(int error_code); const char *MMDB_lib_version(void); int MMDB_read_node(MMDB_s *const mmdb, uint32_t node_number, MMDB_search_node_s *const node);

6、例子 例子1:使用 City 或 Country 库 查询IP所属位置信息 /* this file must be utf8 encode */ #include #include #include #include int main(int argc, char **argv) { char *filename = "./GeoLite2-City.mmdb"; char *ip_address = "114.240.52.162"; MMDB_s mmdb; MMDB_entry_data_s entry_data; MMDB_lookup_result_s result; int gai_error, mmdb_error; int status = MMDB_open(filename, MMDB_MODE_MMAP, &mmdb); if (MMDB_SUCCESS != status) { fprintf(stderr, "Can't open %s - %s\n", filename, MMDB_strerror(status)); if (MMDB_IO_ERROR == status) { fprintf(stderr, "IO error: %s\n", strerror(errno)); } exit(1); } result = MMDB_lookup_string(&mmdb, ip_address, &gai_error, &mmdb_error); if (0 != gai_error) { fprintf(stderr, "Error from getaddrinfo for %s - %s\n", ip_address, gai_strerror(gai_error)); exit(2); } if (MMDB_SUCCESS != mmdb_error) { fprintf(stderr, "Got an error from libmaxminddb: %s\n", MMDB_strerror(mmdb_error)); exit(3); } if (result.found_entry) { /* 获取国家名称(简体中文) */ status = MMDB_get_value(&result.entry, &entry_data, "country", "names", "zh-CN", NULL); /* 获取国家简称(CN/AU/JP等) */ // status = MMDB_get_value(&result.entry, &entry_data, "country", "iso_code", NULL); /* 获取城市名称(简体中文) */ // status = MMDB_get_value(&result.entry, &entry_data, "city", "names", "zh-CN", NULL); if (MMDB_SUCCESS == status) {/* MMDB_get_value 成功 */ if (entry_data.has_data) {/* 找到了想要的数据 */ if (entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) { /* entry_data.utf8_string 返回的不是null-terminated 字符串,需要根据长度自己截取数据 */ fwrite(entry_data.utf8_string, entry_data.data_size, 1, stdout); printf("\n"); } else { printf("data_type = %d\n", entry_data.type); } } else { fprintf(stderr, "MMDB_get_value not found\n"); } } else { fprintf(stderr, "MMDB_get_value failed,%s\n", MMDB_strerror(status)); } } MMDB_close(&mmdb); exit(EXIT_SUCCESS); } 例子2: 使用ASN库查询IP地址的ASN /* this file must be utf8 encode */ #include #include #include #include int main(int argc, char **argv) { char *filename = "./GeoLite2-ASN.mmdb"; char *ip_address = "114.240.52.162"; MMDB_s mmdb; MMDB_entry_data_s entry_data; MMDB_lookup_result_s result; int gai_error, mmdb_error; int status = MMDB_open(filename, MMDB_MODE_MMAP, &mmdb); if (MMDB_SUCCESS != status) { fprintf(stderr, "Can't open %s - %s\n", filename, MMDB_strerror(status)); if (MMDB_IO_ERROR == status) { fprintf(stderr, "IO error: %s\n", strerror(errno)); } exit(1); } result = MMDB_lookup_string(&mmdb, ip_address, &gai_error, &mmdb_error); if (0 != gai_error) { fprintf(stderr, "Error from getaddrinfo for %s - %s\n", ip_address, gai_strerror(gai_error)); exit(2); } if (MMDB_SUCCESS != mmdb_error) { fprintf(stderr, "Got an error from libmaxminddb: %s\n", MMDB_strerror(mmdb_error)); exit(3); } /* ASN DB INFO Example { "autonomous_system_number": 4808 "autonomous_system_organization": "China Unicom Beijing Province Network" } */ if (result.found_entry) { /* 获取ASN */ status = MMDB_get_value(&result.entry, &entry_data, "autonomous_system_organization", NULL); if (MMDB_SUCCESS == status) {/* MMDB_get_value 成功 */ if (entry_data.has_data) {/* 找到了想要的数据 */ if (entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) { /* entry_data.utf8_string 返回的不是null-terminated 字符串,需要根据长度自己截取数据 */ fwrite(entry_data.utf8_string, entry_data.data_size, 1, stdout); printf("\n"); } else { printf("data_type = %d\n", entry_data.type); } } else { fprintf(stderr, "MMDB_get_value not found\n"); } } else { fprintf(stderr, "MMDB_get_value failed,%s\n", MMDB_strerror(status)); } } MMDB_close(&mmdb); exit(EXIT_SUCCESS); }

参考

GeoIP是什么?GeoIP 简介 - 无枫不起浪

GeoIP的使用-C语言版 - LubinLew - 博客园

GeoIP安装使用 - 歪麦博客



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3