Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
leolovenet committed May 20, 2020
0 parents commit 38a6af5
Show file tree
Hide file tree
Showing 10 changed files with 466 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto
156 changes: 156 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@

# Created by https://www.gitignore.io/api/perl,macos,jetbrains+all
# Edit at https://www.gitignore.io/?templates=perl,macos,jetbrains+all

### JetBrains+all ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf

# Generated files
.idea/**/contentModel.xml

# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml

# Gradle
.idea/**/gradle.xml
.idea/**/libraries

# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr

# CMake
cmake-build-*/

# Mongo Explorer plugin
.idea/**/mongoSettings.xml

# File-based project format
*.iws

# IntelliJ
out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Cursive Clojure plugin
.idea/replstate.xml

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties

# Editor-based Rest Client
.idea/httpRequests

# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser

### JetBrains+all Patch ###
# Ignores the whole .idea folder and all .iml files
# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360

.idea/

# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023

*.iml
modules.xml
.idea/misc.xml
*.ipr

# Sonarlint plugin
.idea/sonarlint

### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

### Perl ###
!Build/
.last_cover_stats
/META.yml
/META.json
/MYMETA.*
*.o
*.pm.tdy
*.bs

# Devel::Cover
cover_db/

# Devel::NYTProf
nytprof.out

# Dizt::Zilla
/.build/

# Module::Build
_build/
Build
Build.bat

# Module::Install
inc/

# ExtUtils::MakeMaker
/blib/
/_eumm/
/*.gz
/Makefile
/Makefile.old
/MANIFEST.bak
/pm_to_blib
/*.zip

# End of https://www.gitignore.io/api/perl,macos,jetbrains+all
24 changes: 24 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.

Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.

In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

For more information, please refer to <http://unlicense.org>
69 changes: 69 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# qqwry2mmdb
为 Wireshark 能使用纯真网络 IP 数据库而提供的格式转换工具

![WireShark 集成纯真网络IP数据库](./wireshark-with-qqwry-ip-data.jpg)

## 特性

* 支持自定义 IP 数据库记录,例如向库中增加私网 IP 的归属信息。编辑 `qqwry2mmdb.pl`,打开 `remove_reserved_networks` 开关,新增自己的私人记录。

```perl
$tree->insert_range("192.168.1.1", "192.168.1.1", {
city => {
names => {
en => "众里寻她千百度,蓦然回首阑珊处"
}
},
country => {
names => {
en => "就是您"
}
}
});
```

* 支持根据 IP 属地的数据包过滤, 例如 `ip.geoip.dst_city contains "辽宁"`

![根据IP地址属地过滤](./wireshark-filter.jpg)

## 描述

[Wireshark](https://www.wireshark.org/) 是网络抓包、协议分析、网络问题定位的"瑞士军刀",功能非常强大,我本人非常喜欢的开源网络工具。在网络分析行为中 IP 地址归属地信息查询也是一个很重要的方面。在国内非常出名的,以及维护时间最久的IP归属地数据库应该非 [纯真网络IP数据库](http://www.cz88.net/ip/) 莫属了。至少对于我而言,我希望在 Wireshark 的程序界面里能同时看到捕获到的IP数据包的归属地信息,因此我研究了一下 Wireshark 的源代码,发现它本身已经基于 [libmaxminddb](https://github.com/maxmind/libmaxminddb) 库实现了这个功能(再次为它的强大点赞👍),只不过默认不携带具体的 IP 归属地数据库,需要自行安装。另外 [MaxMind DB](https://github.com/maxmind/MaxMind-DB/blob/master/MaxMind-DB-spec.md) 为开源格式的数据库,因此剩下的工作就简单了,只需要把纯真IP数据库的格式转换到 mmdb 格式,并配置 Wireshark 读取就大功告成了。


## 配置 Wireshark

配置 Wireshark 指定包含 qqwry.mmdb 的目录

![WireShark 配置使用纯真网络IP数据库](./wireshark-config.jpg)

## 安装 qqwry2mmdb.pl

MaxMind DB 自家的 [数据库生成工具](https://github.com/maxmind/MaxMind-DB-Writer-perl) 是基于 Perl 语言编写,因此本项目也是用 Perl 来实现(本想为了便携性用Go重写,但是看了看工作量又懒的再造轮子了),使用并扩展了 [IP::QQWry](https://metacpan.org/pod/IP::QQWry) 库来读取纯真IP库的所有记录。

首先安装 [Perl](https://www.perl.org/get.html) ,然后安装 [cpanm](https://cpanmin.us/), 以及依赖库,`MaxMind::DB::Writer``IP::QQWry::Decoded`

### Linux (CentOS7)

```shell
yum -y install perl perl-CPAN
curl -L https://cpanmin.us | perl - App::cpanminus
cpanm --force MaxMind::DB::Writer IP::QQWry::Decoded

#请自行下载最新版本的 qqwry.dat
perl qqwry2mmdb.pl /your/save/path/of/qqwry.dat
```

### macOS

```shell
brew install perl cpanm
cpanm MaxMind::DB::Writer IP::QQWry::Decoded

#请自行下载最新版本的 qqwry.dat
perl qqwry2mmdb.pl /your/save/path/of/qqwry.dat
```

### windows

`MaxMind::DB::Writer` 不支持该平台
127 changes: 127 additions & 0 deletions lib/IP/QQWry/Dumper.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package IP::QQWry::Dumper;

use 5.008;
use warnings;
use strict;
use base 'IP::QQWry::Decoded';
use Encode;
use Socket;

use feature qw(say);

sub _str {
my $self = shift;
my $str = ""; # fix SUPER class "uninitialized value" warning
my $tmp;

read $self->{fh}, $tmp, 1;
while (ord $tmp > 0) {
$str .= $tmp;
read $self->{fh}, $tmp, 1;
}

return $str;
}

# https://www.perl.com/article/creating-ip-address-tools-from-scratch/
sub long2ip {
my $decimal = shift;
my @bytes = unpack 'CCCC', pack 'N', $decimal;
return join '.', @bytes;
}

sub iterate {
my $self = shift;
my $callback = shift;
die 'must give callback subroutines' unless defined $callback;

my $index;
my $end = ($self->{last_index} - $self->{first_index}) / 7;

for ($index = 0; $index < $end; $index++) {
my ($ip_start, $ip_end, $offset, $tmp);

seek $self->{fh}, $self->{first_index} + $index * 7, 0;
read $self->{fh}, $tmp, 4;
$ip_start = unpack 'V', $tmp;

read $self->{fh}, $tmp, 3;
$offset = unpack 'V', $tmp . chr 0;
die 'record index out of range' unless ($offset >= 8 && $offset < $self->{first_index});

seek $self->{fh}, $offset, 0;
read $self->{fh}, $tmp, 4;
$ip_end = unpack 'V', $tmp;

my ($base, $ext) = (q{}) x 2;
read $self->{fh}, $tmp, 1;
my $mode = ord $tmp;

if ($mode == 1) {
$self->_seek;
$offset = tell $self->{fh};
read $self->{fh}, $tmp, 1;
$mode = ord $tmp;
if ($mode == 2) {
$self->_seek;
$base = $self->_str;
seek $self->{fh}, $offset + 4, 0;
$ext = $self->_ext;
}
else {
seek $self->{fh}, -1, 1;
$base = $self->_str;
$ext = $self->_ext;
}
}
elsif ($mode == 2) {
$self->_seek;
$base = $self->_str;
seek $self->{fh}, $offset + 8, 0;
$ext = $self->_ext;
}
else {
seek $self->{fh}, -1, 1;
$base = $self->_str;
$ext = $self->_ext;
}

# 'CZ88.NET' means we don't have useful information
$base = '' if $base =~ /CZ88\.NET/;
$ext = '' if $ext =~ /CZ88\.NET/;

my @ret = ($base, $ext);
my @converted;

if ($self->encoding) {
@converted = map {decode($self->encoding, $_)} @ret;
}
else {
# then it's either gbk or big5
eval {
@converted = map {decode('gbk', $_)} @ret;
};

if ($@) {
@converted = map {decode('big5', $_)} @ret;
}
}
die "failed to decode" unless @converted;

unshift @converted, long2ip($ip_start), long2ip($ip_end);

last unless $callback->($index, @converted);
}
}

sub dump {
my $self = shift;
$self->iterate(sub {
say join ' ', @_;
return 1;
})
}

1;

__END__
Binary file added qqwry.mmdb
Binary file not shown.
Loading

0 comments on commit 38a6af5

Please sign in to comment.