转载: https://i-meto.com/ipdb-database/
纯真数据库 IPIP.net 格式版: https://github.com/metowolf/qqwry.ipdb
IP 数据库在互联网时代起着举足轻重的作用,例如电商网站的风控系统、通讯软件的登录系统,通常都会将用户的登录 IP 作为一个重要指标进行甄别,因此 IP 数据库的精确性就显得格外重要。
目前网络上提供离线数据库下载的有 qqwry 纯真、IPIP.net、MaxMind 三家。其中 IPIP.net 宣称是基于各电信运营商以及网络服务的 BGP/ASN 数据而分析处理而得来,目前也有众多的知名企业在使用。
2018 年 6 月,IPIP.net 宣布进军 IPv6。在 2019 年 1 月左右,老高在官方放出了全新的 ipdb 格式,能够同时兼容 IPv4/IPv6 地址的查询,另外也大幅提升查询速度。本文就重点来分析一下 ipdb 的文件格式。
基本结构
ipdb 文件在结构上分为三层:文件头、节点区、记录区。
文件头
ipdb 的文件头就是一个简单的 JSON,前 4 个字节表示了 JSON 字符串的长度。
JSON 中提供了数据库的构建时间、节点的数量、多语言的偏移量、支持的字段等等。
节点区
ipdb 的索引方式采用字典树(trie)的方式,首先将 IP 地址转换为二进制形式,然后从根节点开始,遇到二进制位为 0 的时候跳到左子树上,遇到 1 则跳到右子树上。
节点区由若干组节点组成,每组节点长度为 8-byte,其中前 4-byte 表示该节点的左儿子序号,后 4-byte 则是右儿子的节点序号。
举个栗子,我们先把 3.0.0.0
转换成二进制。假设 IPv4 根节点序号为 96,那么根据第 1 个二进制位 0,下一跳应该跳转到 96 节点的左儿子 97 上。以此类推,当跳到序号大于节点总数的时候(还记得文件头中的信息吗),就意味着找到最终的数据了。
那么如何同时兼容 IPv4 和 IPv6 呢?其实早在 IPv6 协议提出的时候,工作组就专门在 IPv6 中划分了一段地址 ::ffff:x.x.x.x/96
为 IPv4 提供兼容。
所有 IPv4 地址都会先转换成 IPv6,然后再从根节点开始搜寻。为了加快查询速度,我们可以在读取数据库的时候先缓存好 IPv4 的根节点,后续查询的时候可以直接跳过前面的节点。
数据区
数据区分为若干组,每组前 2-byte 为数据长度 vlen,后面跟着一个 vlen 长度的字符串,储存了该 IP 段的所有位置信息,用制表符 \t
分隔。
ipdb 数据库加入了多语言的特性,具体实现方法是将不同的语言分段拼接起来,然后通过头文件里的语言偏移值来分别提取。
代码
讲完原理,我们可以开始动手造一个解析 ipdb 文件的库了。
具体实现代码可以参考:
转载请注明:爱开源 » IPIP.net 地址库格式分析