IPIP.net 地址库格式分析

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 地址都会先转换成 IPv6,然后再从根节点开始搜寻。为了加快查询速度,我们可以在读取数据库的时候先缓存好 IPv4 的根节点,后续查询的时候可以直接跳过前面的节点。

数据区

数据区分为若干组,每组前 2-byte 为数据长度 vlen,后面跟着一个 vlen 长度的字符串,储存了该 IP 段的所有位置信息,用制表符 \t 分隔。

ipdb 数据库加入了多语言的特性,具体实现方法是将不同的语言分段拼接起来,然后通过头文件里的语言偏移值来分别提取。

数据区

代码

讲完原理,我们可以开始动手造一个解析 ipdb 文件的库了。
具体实现代码可以参考:

后续再教大家如何把 ipdb 转换成 txt 格式(高见打,逃

加入对话

11条评论

  1. 请问下楼主为什么找到比MetaData 中的nodeCount 大的节点就是找到了呢

  2. 举个栗子,我们先把 3.0.0.0 转换成二进制。假设 IPv4 根节点序号为 96,那么根据第 1 个二进制位 0,下一跳应该跳转到 96 节点的左儿子 97 上。以此类推,当跳到序号大于节点总数的时候(还记得文件头中的信息吗),就意味着找到最终的数据了。
    —————————————-
    这个怎么理解?懵逼ing…. 囧

留下评论

电子邮件地址不会被公开。 必填项已用*标注