目前MaxMind对MMDB的读写支持如下
Writer:
perl
Reader:
C
C#
Java
Perl
PHP
Python
所以本文着重介绍如何快速使用perl生成mmdb文件,以及查询mmdb基本原理
工作环境:Centos 6.5
一、安装perl环境
忽略解压、cd等基础操作
-
1 .下载perl5 https://www.perl.org/get.html#unix_like 我下载的是Source版(需使用新版perl5,centos默认的perl5不支持)
-
2 .编译 安装
- configure.gnu
- make
- make install
-
3 .安装 cpan,git
- yum install cpan git
-
4 .备份替换系统perl文件
- mv /usr/bin/perl /usr/bin/perk.bak
- ln -s /usr/local/bin/perl /usr/bin/perl
-
5.git clone mmdb writer
-
6.切换至writer目录,下载cpanm并安装模块依赖(所需时间很长)
- curl -LO http://xrl.us/cpanm
- perl cpanm --installdeps .
-
7.安装mmdb Writer模块
- perl Build.PL
- ./Build install
二、生成库文件
- 编写perl代码,下面为样例,将读local.db文件,生成dt.mmdb文件
use MaxMind::DB::Writer::Tree;
use Net::Works::Network;
use strict;
use warnings;
use Path::Class;
use autodie;
my %types = (
product => 'utf8_string',
rack => 'utf8_string',
administrator => 'utf8_string',
room => 'utf8_string',
);
my $tree = MaxMind::DB::Writer::Tree->new(
ip_version => 4,
record_size => 24,
database_type => 'kevin_test',
languages => [ 'en' ],
description => { en => 'Used in MarkDown display' },
map_key_type_callback => sub { $types{ $_[0] } },
);
sub tree_insert_network{
my $network = Net::Works::Network->new_from_string( string => $_[1] );
$_[0]->insert_network(
$network,
{
product => $_[2],
rack => $_[3],
administrator => $_[4],
room => $_[5]
},
);
}
sub build_tree{
my $dir = dir(".");
my $file = $dir->file($_[0]);
my $content = $file->slurp();
my $file_handle = $file->openr();
binmode($file_handle, ":utf8");
while( my $line = $file_handle->getline() ) {
$line =~ s/^\s+|\s+$//g;
if ($line eq "") {
next;
}
my @values = split('\|', $line);
for (my $i= 1;$i <= 4;$i++){
if (!defined $values[$i]) {
$values[$i] = ""
}
}
my @networks = split(',', $values[0]);
foreach my $net (@networks) {
tree_insert_network($tree, $net, $values[1], $values[2], $values[3], $values[4]);
}
}
}
build_tree('local.db', $tree);
open my $fh, '>:bytes', 'dt.mmdb';
$tree->write_tree($fh);
- 编辑local.db文件
1.1.1.1/32|Alipapa.Portal.COM.发布系统|西单.4-2号机房.01-21|kevin|西单
分别表示 IP/掩码|产品线|机架|管理员|机房 (纯属虚构)
- perl test.pl
MMDB查询原理
一.简单介绍下ipv4地址格式
我们所常见的ipv4地址如1.1.1.1均是点分十进制描述,以便用户来书写记忆,操作系统需要对该地址进行转义生成32位2进制地址,如上面的地址1.1.1.1将转换为00000001 00000001 00000001 00000001
二.mmdb文件三部分
MMDB文件内容为二进制格式,其内容分为三大块:搜索树、数据段和元数据
为了便于读者理解,我在此先介绍元数据
1.元数据区
(本文仅介绍对文件结构有影响的元数据,其他描述性质的元数据不在此讨论,有需要的读者请参考文尾的官方文档)
元数据区记录了该mmdb文件的有关描述信息,以及对搜索数据有关的必要字段,元数据区位于文件尾部,以\xab\xcd\xefMaxMind.com字串分割元数据区与数据段,具体的存储结构与数据段类似。
- node_count 节点数量
记录搜索树中有多少节点 - record_size 记录位大小
每个搜索树节点有两个record - ip_version ip地址版本
IPV4 或 IPV6
2.搜索树
搜索树用来通过ip来索引数据,由node_count 个node节点组成,每个节点有2个record,以24位size大小为例:
| <--- node --->|
| 23 .. 0 | 23 .. 0 |
record的值为node号
搜索树位于文件首部
3.数据段
数据段的值为某ip所对应的具体内容,如城市、坐标(当然也可在生成时自定义);数据段位于文件中部,与前边的搜索树以16个8位的null分割。
- 字段类型:常见类型 UTF-8 string、pointer、double、map
(其他类型请参考官网,如首3位为0的扩展字段)- pointer:指针类型,类型值为1
- UTF-8 string: UTF字串类型,类型值为2
- double:双精度数字,类型值为3
- map:映射类型,类型值为7
- 类型字段结构:
- 8位表示,前三位为字段类型,后五位为有效载荷
- 有效载荷:通常为该字段在当前类型下,实际存储的数量;指针和映射类型除外,指针的载荷为数据区域指针偏移地址,映射的载荷为有多少k-v对
- 例如:
- 映射类型 4个k-v对 -->11100100
- UTF8类型 13个字符 -->01001101
- 存储结构:
- 首位为映射字段,表示该数据块有N个k-v
- N个字段块,每个块首部指出该字段类型,其后为具体的值
简介mmdb文件查询算法
我们以1.1.1.1这个ip地址为例:
- 1.将该地址转置成二进制形式00000001 00000001 00000001 00000001
- 2.取大端第一位,在搜索树查看起始node的recore,因为值为0故选择大端的recore,判断该值,有如下三种情况
- 该值大小小于node_count 则表明该值指向搜索树中的另外一个节点,则按照下一位的值重复此搜索
- 若值等于node_count则表明该ip在此mmdb文件中不存在
- 若值大于node_count则表明该指针指向了数据段
- 3.若该值指向了数据段,则判断该值所表示在数据段的偏移量
$offset = value - nodecount - 16$
16为数据段和搜索树中的16个8位null - 4.取到在数据段的偏移量后,找到该偏移量指向的区域,首位为map类型指示了该段有多少个kv对,每个字段依次先指明字段类型然后紧随值类型。
附:
MaxMind官方文档:http://maxmind.github.io/MaxMind-DB/
若想支持查询内网IP需要修改MMDB生成脚本的pm文件
./MaxMind-DB-Writer-perl/lib/MaxMind/DB/Writer/Tree.pm
删除307行左右关于内网保留IP的内容
下文为一个二进制索引的例子:
查询1.1.1.1加粗字体为路径
0000000: 00000000 00000000 00000001 00000000 00000000 00101111 ...../
0000006: 00000000 00000000 00000010 00000000 00000000 00100011 .....#
000000c: 00000000 00000000 00000011 00000000 00000000 10011111 ......
0000012: 00000000 00000000 00000100 00000000 00000000 10011111 ......
0000018: 00000000 00000000 00000101 00000000 00000000 00100000 .....
000001e: 00000000 00000000 00000110 00000000 00000000 10011111 ......
0000024: 00000000 00000000 00000111 00000000 00000000 10011111 ......
000002a: 00000000 00000000 10011111 00000000 00000000 00001000 ......
0000030: 00000000 00000000 00001001 00000000 00000000 10011111 ......
0000036: 00000000 00000000 00001010 00000000 00000000 10011111 ......
000003c: 00000000 00000000 00001011 00000000 00000000 10011111 ......
0000042: 00000000 00000000 00001100 00000000 00000000 10011111 ......
0000048: 00000000 00000000 00001101 00000000 00000000 10011111 ......
000004e: 00000000 00000000 00001110 00000000 00000000 10011111 ......
0000054: 00000000 00000000 00001111 00000000 00000000 10011111 ......
000005a: 00000000 00000000 10011111 00000000 00000000 00010000 ......
0000060: 00000000 00000000 00010001 00000000 00000000 10011111 ......
0000066: 00000000 00000000 00010010 00000000 00000000 10011111 ......
000006c: 00000000 00000000 00010011 00000000 00000000 10011111 ......
0000072: 00000000 00000000 00010100 00000000 00000000 10011111 ......
0000078: 00000000 00000000 00010101 00000000 00000000 10011111 ......
000007e: 00000000 00000000 00010110 00000000 00000000 10011111 ......
0000084: 00000000 00000000 00010111 00000000 00000000 10011111 ......
000008a: 00000000 00000000 10011111 00000000 00000000 00011000 ......
0000090: 00000000 00000000 00011001 00000000 00000000 10011111 ......
0000096: 00000000 00000000 00011010 00000000 00000000 10011111 ......
000009c: 00000000 00000000 00011011 00000000 00000000 10011111 ......
00000a2: 00000000 00000000 00011100 00000000 00000000 10011111 ......
00000a8: 00000000 00000000 00011101 00000000 00000000 10011111 ......
00000ae: 00000000 00000000 00011110 00000000 00000000 10011111 ......
00000b4: 00000000 00000000 00011111 00000000 00000000 10011111 ......
00000ba: 00000000 00000000 10011111 00000000 00000000 10101111 ......
00000c0: 00000000 00000000 00100001 00000000 00000000 10011111 ..!...
00000c6: 00000000 00000000 10011111 00000000 00000000 00100010 ....."
00000cc: 00000000 00000000 10011111 00000000 00000000 10011111 ......
00000d2: 00000000 00000000 10011111 00000000 00000000 00100100 .....$
00000d8: 00000000 00000000 00100101 00000000 00000000 00101011 ..%..+
00000de: 00000000 00000000 00100110 00000000 00000000 10011111 ..&...
00000e4: 00000000 00000000 10011111 00000000 00000000 00100111 .....'
00000ea: 00000000 00000000 00101000 00000000 00000000 10011111 ..(...
00000f0: 00000000 00000000 00101001 00000000 00000000 10011111 ..)...
00000f6: 00000000 00000000 00101010 00000000 00000000 10011111 ..*...
00000fc: 00000000 00000000 10011111 00000000 00000000 10011111 ......
0000102: 00000000 00000000 10011111 00000000 00000000 00101100 .....,
0000108: 00000000 00000000 10011111 00000000 00000000 00101101 .....-
000010e: 00000000 00000000 10011111 00000000 00000000 00101110 ......
0000114: 00000000 00000000 10011111 00000000 00000000 10011111 ......
000011a: 00000000 00000000 00110000 00000000 00000000 01000100 ..0..D
0000120: 00000000 00000000 10011111 00000000 00000000 00110001 .....1
0000126: 00000000 00000000 00110010 00000000 00000000 10011111 ..2...
000012c: 00000000 00000000 10011111 00000000 00000000 00110011 .....3
0000132: 00000000 00000000 00110100 00000000 00000000 00111110 ..4..>
0000138: 00000000 00000000 00110101 00000000 00000000 10011111 ..5...
000013e: 00000000 00000000 10011111 00000000 00000000 00110110 .....6
0000144: 00000000 00000000 10011111 00000000 00000000 00110111 .....7
000014a: 00000000 00000000 10011111 00000000 00000000 00111000 .....8
0000150: 00000000 00000000 10011111 00000000 00000000 00111001 .....9
0000156: 00000000 00000000 10011111 00000000 00000000 00111010 .....:
000015c: 00000000 00000000 10011111 00000000 00000000 00111011 .....;
0000162: 00000000 00000000 10011111 00000000 00000000 00111100 .....<
0000168: 00000000 00000000 10011111 00000000 00000000 00111101 .....=
000016e: 00000000 00000000 10011111 00000000 00000000 10011111 ......
0000174: 00000000 00000000 00111111 00000000 00000000 10011111 ..?...
000017a: 00000000 00000000 01000000 00000000 00000000 10011111 ..@...
0000180: 00000000 00000000 01000001 00000000 00000000 10011111 ..A...
0000186: 00000000 00000000 01000010 00000000 00000000 10011111 ..B...
000018c: 00000000 00000000 01000011 00000000 00000000 10011111 ..C...
0000192: 00000000 00000000 10011111 00000000 00000000 10011111 ......
0000198: 00000000 00000000 01000101 00000000 00000000 10011110 ..E...
000019e: 00000000 00000000 01000110 00000000 00000000 10011111 ..F...
00001a4: 00000000 00000000 01000111 00000000 00000000 10001011 ..G...
00001aa: 00000000 00000000 01001000 00000000 00000000 01110101 ..H..u
00001b0: 00000000 00000000 01001001 00000000 00000000 10011111 ..I...
00001b6: 00000000 00000000 01001010 00000000 00000000 10011111 ..J...
00001bc: 00000000 00000000 01001011 00000000 00000000 01101110 ..K..n
00001c2: 00000000 00000000 01001100 00000000 00000000 01100000 ..L..`
00001c8: 00000000 00000000 01001101 00000000 00000000 10011111 ..M...
00001ce: 00000000 00000000 01001110 00000000 00000000 10011111 ..N...
00001d4: 00000000 00000000 01001111 00000000 00000000 10011111 ..O...
00001da: 00000000 00000000 01010000 00000000 00000000 10011111 ..P...
00001e0: 00000000 00000000 01010001 00000000 00000000 10011111 ..Q...
00001e6: 00000000 00000000 01010010 00000000 00000000 10011111 ..R...
00001ec: 00000000 00000000 01010011 00000000 00000000 10011111 ..S...
00001f2: 00000000 00000000 01010100 00000000 00000000 10011111 ..T...
00001f8: 00000000 00000000 01010101 00000000 00000000 10011111 ..U...
00001fe: 00000000 00000000 01010110 00000000 00000000 10011111 ..V...
0000204: 00000000 00000000 01010111 00000000 00000000 10011111 ..W...
000020a: 00000000 00000000 01011000 00000000 00000000 10011111 ..X...
0000210: 00000000 00000000 01011001 00000000 00000000 01011111 ..Y.._
0000216: 00000000 00000000 01011010 00000000 00000000 10011111 ..Z...
000021c: 00000000 00000000 01011011 00000000 00000000 10011111 ..[...
0000222: 00000000 00000000 01011100 00000000 00000000 10011111 .....
0000228: 00000000 00000000 01011101 00000000 00000000 10011111 ..]...
000022e: 00000000 00000000 01011110 00000000 00000000 10011111 ..^...
0000234: 00000000 00000000 10011111 00000000 00000000 10011111 ......
000023a: 00000000 00000000 10011111 00000000 00000000 10011111 ......
0000240: 00000000 00000000 01100001 00000000 00000000 10011111 ..a...
0000246: 00000000 00000000 10011111 00000000 00000000 01100010 .....b
000024c: 00000000 00000000 10011111 00000000 00000000 01100011 .....c
0000252: 00000000 00000000 01100100 00000000 00000000 10011111 ..d...
0000258: 00000000 00000000 01100101 00000000 00000000 10011111 ..e...
000025e: 00000000 00000000 01100110 00000000 00000000 10011111 ..f...
0000264: 00000000 00000000 01100111 00000000 00000000 10011111 ..g...
000026a: 00000000 00000000 10011111 00000000 00000000 01101000 .....h
0000270: 00000000 00000000 10011111 00000000 00000000 01101001 .....i
0000276: 00000000 00000000 01101010 00000000 00000000 10011111 ..j...
000027c: 00000000 00000000 01101011 00000000 00000000 10011111 ..k...
0000282: 00000000 00000000 01101100 00000000 00000000 10011111 ..l...
0000288: 00000000 00000000 10011111 00000000 00000000 01101101 .....m
000028e: 00000000 00000000 10011111 00000000 00000000 10011111 ......
0000294: 00000000 00000000 01101111 00000000 00000000 10011111 ..o...
000029a: 00000000 00000000 10011111 00000000 00000000 01110000 .....p
00002a0: 00000000 00000000 01110001 00000000 00000000 10011111 ..q...
00002a6: 00000000 00000000 10011111 00000000 00000000 01110010 .....r
00002ac: 00000000 00000000 01110011 00000000 00000000 10011111 ..s...
00002b2: 00000000 00000000 01110100 00000000 00000000 10011111 ..t...
00002b8: 00000000 00000000 10011111 00000000 00000000 10011111 ......
00002be: 00000000 00000000 10011111 00000000 00000000 01110110 .....v
00002c4: 00000000 00000000 01110111 00000000 00000000 10011111 ..w...
00002ca: 00000000 00000000 01111000 00000000 00000000 10011111 ..x...
00002d0: 00000000 00000000 01111001 00000000 00000000 10011111 ..y...
00002d6: 00000000 00000000 01111010 00000000 00000000 01111110 ..z..~
00002dc: 00000000 00000000 10011111 00000000 00000000 01111011 .....{
00002e2: 00000000 00000000 01111100 00000000 00000000 10011111 ..|...
00002e8: 00000000 00000000 01111101 00000000 00000000 10011111 ..}...
00002ee: 00000000 00000000 10011111 00000000 00000000 10011111 ......
00002f4: 00000000 00000000 10011111 00000000 00000000 01111111 ......
00002fa: 00000000 00000000 10000000 00000000 00000000 10011111 ......
0000300: 00000000 00000000 10000001 00000000 00000000 10011111 ......
0000306: 00000000 00000000 10011111 00000000 00000000 10000010 ......
000030c: 00000000 00000000 10011111 00000000 00000000 10000011 ......
0000312: 00000000 00000000 10000100 00000000 00000000 10011111 ......
0000318: 00000000 00000000 10011111 00000000 00000000 10000101 ......
000031e: 00000000 00000000 10011111 00000000 00000000 10000110 ......
0000324: 00000000 00000000 10000111 00000000 00000000 10011111 ......
000032a: 00000000 00000000 10001000 00000000 00000000 10011111 ......
0000330: 00000000 00000000 10011111 00000000 00000000 10001001 ......
0000336: 00000000 00000000 10001010 00000000 00000000 10011111 ......
000033c: 00000000 00000000 10011111 00000000 00000000 10011111 ......
0000342: 00000000 00000000 10001100 00000000 00000000 10011111 ......
0000348: 00000000 00000000 10011111 00000000 00000000 10001101 ......
000034e: 00000000 00000000 10011111 00000000 00000000 10001110 ......
0000354: 00000000 00000000 10001111 00000000 00000000 10011111 ......
000035a: 00000000 00000000 10010000 00000000 00000000 10011111 ......
0000360: 00000000 00000000 10010001 00000000 00000000 10011111 ......
0000366: 00000000 00000000 10010010 00000000 00000000 10011111 ......
000036c: 00000000 00000000 10010011 00000000 00000000 10011111 ......
0000372: 00000000 00000000 10010100 00000000 00000000 10011111 ......
0000378: 00000000 00000000 10010101 00000000 00000000 10011111 ......
000037e: 00000000 00000000 10010110 00000000 00000000 10011111 ......
0000384: 00000000 00000000 10010111 00000000 00000000 10011111 ......
000038a: 00000000 00000000 10011111 00000000 00000000 10011000 ......
0000390: 00000000 00000000 10011111 00000000 00000000 10011001 ......
0000396: 00000000 00000000 10011111 00000000 00000000 10011010 ......
000039c: 00000000 00000000 10011011 00000000 00000000 10011111 ......
00003a2: 00000000 00000000 10011100 00000000 00000000 10011111 ......
00003a8: 00000000 00000000 10011101 00000000 00000000 10011111 ......
00003ae: 00000000 00000000 10011111 00000000 00000000 10011111 ......
00003b4: 00000000 00000000 10011111 00000000 00000000 10011111 ......
00003ba: 00000000 00000000 00000000 00000000 00000000 00000000 ......
00003c0: 00000000 00000000 00000000 00000000 00000000 00000000 ......
00003c6: 00000000 00000000 00000000 00000000 11100100 01001101 .....M
00003cc: 01100001 01100100 01101101 01101001 01101110 01101001 admini
00003d2: 01110011 01110100 01110010 01100001 01110100 01101111 strato
00003d8: 01110010 01000101 01101011 01100101 01110110 01101001 rEkevi
00003de: 01101110 01000111 01110000 01110010 01101111 01100100 nGprod
00003e4: 01110101 01100011 01110100 01011101 00000010 01000001 uct].A
00003ea: 01101100 01101001 01110000 01100001 01110000 01100001 lipapa
00003f0: 00101110 01010000 01101111 01110010 01110100 01100001 .Porta
00003f6: 01101100 00101110 01000011 01001111 01001101 00101110 l.COM.
00003fc: 11100101 10001111 10010001 11100101 10111000 10000011 ......
0000402: 11100111 10110011 10111011 11100111 10111011 10011111 ......
0000408: 01000100 01110010 01100001 01100011 01101011 01011001 DrackY
000040e: 11101000 10100101 10111111 11100101 10001101 10010101 ......
0000414: 00101110 00110100 00101101 00110010 11100101 10001111 .4-2..
000041a: 10110111 11100110 10011100 10111010 11100110 10001000 ......
0000420: 10111111 00101110 00110000 00110001 00101101 00110010 ..01-2
0000426: 00110001 01000100 01110010 01101111 01101111 01101101 1Droom
000042c: 01000110 11101000 10100101 10111111 11100101 10001101 F.....
0000432: 10010101 10101011 11001101 11101111 01001101 01100001 ....Ma
0000438: 01111000 01001101 01101001 01101110 01100100 00101110 xMind.
000043e: 01100011 01101111 01101101 11101001 01011011 01100010 com.[b
0000444: 01101001 01101110 01100001 01110010 01111001 01011111 inary_
000044a: 01100110 01101111 01110010 01101101 01100001 01110100 format
0000450: 01011111 01101101 01100001 01101010 01101111 01110010 _major
0000456: 01011111 01110110 01100101 01110010 01110011 01101001 versi
000045c: 01101111 01101110 10100001 00000010 01011011 01100010 on..[b
0000462: 01101001 01101110 01100001 01110010 01111001 01011111 inary
0000468: 01100110 01101111 01110010 01101101 01100001 01110100 format
000046e: 01011111 01101101 01101001 01101110 01101111 01110010 _minor
0000474: 01011111 01110110 01100101 01110010 01110011 01101001 _versi
000047a: 01101111 01101110 10100000 01001011 01100010 01110101 on.Kbu
0000480: 01101001 01101100 01100100 01011111 01100101 01110000 ild_ep
0000486: 01101111 01100011 01101000 00000100 00000010 01011000 och..X
000048c: 01000110 10001011 10100000 01001101 01100100 01100001 F..Mda
0000492: 01110100 01100001 01100010 01100001 01110011 01100101 tabase
0000498: 01011111 01110100 01111001 01110000 01100101 01001010 typeJ
000049e: 01101011 01100101 01110110 01101001 01101110 01011111 kevin
00004a4: 01110100 01100101 01110011 01110100 01001011 01100100 testKd
00004aa: 01100101 01110011 01100011 01110010 01101001 01110000 escrip
00004b0: 01110100 01101001 01101111 01101110 11100001 01000010 tion.B
00004b6: 01100101 01101110 01011000 01010101 01110011 01100101 enXUse
00004bc: 01100100 00100000 01101001 01101110 00100000 01001101 d in M
00004c2: 01100001 01110010 01101011 01000100 01101111 01110111 arkDow
00004c8: 01101110 00100000 01100100 01101001 01110011 01110000 n disp
00004ce: 01101100 01100001 01111001 01001010 01101001 01110000 layJip
00004d4: 01011111 01110110 01100101 01110010 01110011 01101001 _versi
00004da: 01101111 01101110 10100001 00000100 01001001 01101100 on..Il
00004e0: 01100001 01101110 01100111 01110101 01100001 01100111 anguag
00004e6: 01100101 01110011 00000001 00000100 01000010 01100101 es..Be
00004ec: 01101110 01001010 01101110 01101111 01100100 01100101 nJnode
00004f2: 01011111 01100011 01101111 01110101 01101110 01110100 _count
00004f8: 11000001 10011111 01001011 01110010 01100101 01100011 ..Krec
00004fe: 01101111 01110010 01100100 01011111 01110011 01101001 ord_si
0000504: 01111010 01100101 10100001 00011000 ze..