Git Product home page Git Product logo

mmdbctl's Introduction

IPinfo IPinfo mmdbctl

mmdbctl is an MMDB file management CLI by IPinfo.io that provides you the following features:

  • Read data for IPs in an MMDB file.
  • Import data in non-MMDB format into MMDB.
  • Export data from MMDB format into non-MMDB format.
  • See the difference between two MMDB files.
  • Print the metadata of an MMDB file.
  • Check that an MMDB file is not corrupted or invalid.

Installation

The mmdbctl CLI is available for download via multiple mechanisms.

macOS

Install the latest amd64 version:

curl -Ls https://github.com/ipinfo/mmdbctl/releases/download/mmdbctl-1.4.3/macos.sh | sh

Debian / Ubuntu (amd64)

curl -Ls https://github.com/ipinfo/mmdbctl/releases/download/mmdbctl-1.4.3/deb.sh | sh

OR

curl -LO https://github.com/ipinfo/mmdbctl/releases/download/mmdbctl-1.4.3/mmdbctl_1.4.3.deb
sudo dpkg -i mmdbctl_1.4.3.deb

Windows Powershell

Note: run powershell as administrator before executing this command.

iwr -useb https://github.com/ipinfo/mmdbctl/releases/download/mmdbctl-1.4.3/windows.ps1 | iex

Using go install

Make sure that $GOPATH/bin is in your $PATH, because that's where this gets installed:

go install github.com/ipinfo/mmdbctl@latest

Using curl/wget

The pre-built binaries for all platforms are available on GitHub via artifacts in releases. You need to simply download, unpack and move them to your shell's binary search path.

The following OS & arch combinations are supported (if you use one not listed on here, please open an issue):

darwin_amd64
darwin_arm64
dragonfly_amd64
freebsd_386
freebsd_amd64
freebsd_arm
freebsd_arm64
linux_386
linux_amd64
linux_arm
linux_arm64
netbsd_386
netbsd_amd64
netbsd_arm
netbsd_arm64
openbsd_386
openbsd_amd64
openbsd_arm
openbsd_arm64
solaris_amd64
windows_386
windows_amd64
windows_arm

After choosing a platform PLAT from above, run:

# for Windows, use ".zip" instead of ".tar.gz"
curl -LO https://github.com/ipinfo/mmdbctl/releases/download/mmdbctl-1.4.3/mmdbctl_1.4.3_${PLAT}.tar.gz
# OR
wget https://github.com/ipinfo/mmdbctl/releases/download/mmdbctl-1.4.3/mmdbctl_1.4.3_${PLAT}.tar.gz
tar -xvf mmdbctl_1.4.3_${PLAT}.tar.gz
mv mmdbctl_1.4.3_${PLAT} /usr/local/bin/mmdbctl

Using git

Installing from source requires at least the Golang version specified in go.mod. You can install the Golang toolchain from the official site.

Once the correct Golang version is installed, simply clone the repository and install the binary:

git clone https://github.com/ipinfo/mmdbctl
cd mmdbctl
go install .
$GOPATH/bin/mmdbctl

You can add $GOPATH/bin to your $PATH to access mmdbctl directly from anywhere.

Alternatively, you can do the following to output the binary somewhere specific:

git clone https://github.com/ipinfo/mmdbctl
cd mmdbctl
go build -o <path> .

Replace <path> with the required location.

Quick Start

This will help you quickly get started with the mmdbctl CLI.

Default Help Message

By default, invoking the CLI shows a help message:

mmdbctl

Reading

You can read from MMDB files in various different ways - as individual IPs, CIDRs or IP ranges, coming from the command line as arguments, or from files, or from stdin.

Pretty JSON format:

$ mmdbctl read -f json-pretty 8.8.8.8 location.mmdb
{
  "city": "Mountain View",
  "country": "US",
  "geoname_id": "5375480",
  "latitude": "37.4056",
  "longitude": "-122.0775",
  "postalcode": "94043",
  "region": "California",
  "timezone": "America/Los_Angeles"
}

CSV format:

$ mmdbctl read -f csv 8.8.8.8 location.mmdb
ip,city,country,geoname_id,latitude,longitude,postalcode,region,timezone
8.8.8.8,Mountain View,US,5375480,37.4056,-122.0775,94043,California,America/Los_Angeles

TSV format:

$ mmdbctl read -f tsv 8.8.8.8 location.mmdb
ip	city	country	geoname_id	latitude	longitude	postalcode	region	timezone
8.8.8.8	Mountain View	US	5375480	37.4056	-122.0775	94043	California	America/Los_Angeles

Via a file:

$ cat ips.txt
8.8.8.8
8.8.8.0/31
8.8.8.0-8.8.8.1
8.8.8.0,8.8.8.1

$ mmdbctl read ips.txt location.mmdb | sort -u
{"city":"Mountain View","country":"US","geoname_id":"5375480","latitude":"37.4056","longitude":"-122.0775","postalcode":"94043","region":"California","timezone":"America/Los_Angeles"}

Via stdin:

$ echo 8.8.8.8 | mmdbctl read location.mmdb
{"city":"Mountain View","country":"US","geoname_id":"5375480","latitude":"37.4056","longitude":"-122.0775","postalcode":"94043","region":"California","timezone":"America/Los_Angeles"}

Multiple inputs are also possible - these all return the same thing:

$ echo -e '8.8.8.8\n1.2.3.4' | mmdbctl read location.mmdb
$ mmdbctl read 8.8.8.8 1.2.3.4 location.mmdb
{"city":"Mountain View","country":"US","geoname_id":"5375480","latitude":"37.4056","longitude":"-122.0775","postalcode":"94043","region":"California","timezone":"America/Los_Angeles"}
{"city":"Brisbane","country":"AU","geoname_id":"2174003","latitude":"-27.48203","longitude":"153.01358","postalcode":"4101","region":"Queensland","timezone":"Australia/Brisbane"}

Can check CIDRs and ranges - these will all return the same thing:

$ mmdbctl read 8.8.8.0/31 location.mmdb
$ mmdbctl read 8.8.8.0-8.8.8.1 location.mmdb
$ mmdbctl read 8.8.8.0,8.8.8.1 location.mmdb
{"city":"Mountain View","country":"US","geoname_id":"5375480","latitude":"37.4056","longitude":"-122.0775","postalcode":"94043","region":"California","timezone":"America/Los_Angeles"}
{"city":"Mountain View","country":"US","geoname_id":"5375480","latitude":"37.4056","longitude":"-122.0775","postalcode":"94043","region":"California","timezone":"America/Los_Angeles"}
{"city":"Mountain View","country":"US","geoname_id":"5375480","latitude":"37.4056","longitude":"-122.0775","postalcode":"94043","region":"California","timezone":"America/Los_Angeles"}

Importing

Importing allows taking in files as CSV/TSV/JSON, and outputting an MMDB file.

Importing is one of the most powerful/flexible features in mmdbctl. However, we only allow strings throughout the data at the current time.

See mmdbctl import --help for full details on usage.

Here are some basic examples:

# basic CSV importing into MMDB.
$ mmdbctl import --in data.csv --out data.mmdb

# generate MMDB from a TSV file containing IPv4 data.
$ cat data.tsv | mmdbctl import --ip 4 --tsv --out data.mmdb

# don't include the implicit `network` field in the output MMDB:
$ mmdbctl import --no-network --in data.csv --out data.mmdb

# generate an MMDB without any fields, just IP ranges that meet a criteria.
$ mmdbctl import                                                              \
    --size 24 --no-fields --ip 4                                              \
    --in anycast.csv --out anycast.mmdb

Exporting

Exporting allows taking in an MMDB file and outputting CSV/TSV/JSON.

See mmdbctl export --help for full details on usage.

# basic export.
$ mmdbctl export data.mmdb data.csv

# basic export without a header.
$ mmdbctl export --no-header data.mmdb data.csv

# just see the number of entries it'd output.
$ mmdbctl export --no-header --format csv data.mmdb | wc -l

Metadata

You can retrieve data in the metadata section of the MMDB file using the metadata subcommand.

Pretty format:

$ mmdbctl metadata location.mmdb
- Binary Format 2.0
- Database Type ipinfo location.mmdb
- IP Version    4
- Record Size   32
- Node Count    123456789
- Description
    en ipinfo location.mmdb
- Languages     en
- Build Epoch   123456789

JSON format:

$ mmdbctl metadata -f json location.mmdb
{
    "binary_format": "2.0",
    "db_type": "ipinfo location.mmdb",
    "ip": 4,
    "record_size": 32,
    "node_count": 123456789,
    "description": {
        "en": "ipinfo location.mmdb"
    },
    "languages": [
        "en"
    ],
    "build_epoch": 123456789
}

Verification

You can verify if a MMDB file is correctly structured with the verify subcommand:

$ mmdbctl verify location.mmdb
valid

Let's force it to be invalid and check again:

$ cp location.mmdb location-tmp.mmdb
$ cat location.mmdb >> location-tmp.mmdb
$ mmdbctl verify location-tmp.mmdb
invalid: received decoding error (the MaxMind DB file's data section contains bad data (uint16 size of 11)) at offset of 13825601

Auto-Completion

Auto-completion is supported for at least the following shells:

bash
zsh
fish

NOTE: it may work for other shells as well because the implementation is in Golang and is not necessarily shell-specific.

Installation

Installing auto-completions is as simple as running one command (works for bash, zsh and fish shells):

mmdbctl completion install

If you want to customize the installation process (e.g. in case the auto-installation doesn't work as expected), you can request the actual completion script for each shell:

# get bash completion script
mmdbctl completion bash

# get zsh completion script
mmdbctl completion zsh

# get fish completion script
mmdbctl completion fish

Shell not listed?

If your shell is not listed here, you can open an issue.

Note that as long as the COMP_LINE environment variable is provided to the binary itself, it will output completion results. So if your shell provides a way to pass COMP_LINE on auto-completion attempts to a binary, then have your shell do that with the mmdbctl binary itself (or any of our binaries).

Color Output

Disabling Color Output

All our CLIs respect either the --nocolor flag or the NO_COLOR environment variable to disable color output.

Color on Windows

To enable color support for the Windows command prompt, run the following to enable Console Virtual Terminal Sequences.

REG ADD HKCU\CONSOLE /f /v VirtualTerminalLevel /t REG_DWORD /d 1

You can disable this by running the following:

REG DELETE HKCU\CONSOLE /f /v VirtualTerminalLevel

Other IPinfo Tools

There are official IPinfo client libraries available for many languages including PHP, Python, Go, Java, Ruby, and many popular frameworks such as Django, Rails and Laravel. There are also many third party libraries and integrations available for our API.

See https://ipinfo.io/developers/libraries for more details.

About IPinfo

Founded in 2013, IPinfo prides itself on being the most reliable, accurate, and in-depth source of IP address data available anywhere. We process terabytes of data to produce our custom IP geolocation, company, carrier, VPN detection, hosted domains, and IP type data sets. Our API handles over 40 billion requests a month for businesses and developers.

image

mmdbctl's People

Contributors

abdullahdevrel avatar abu-usama avatar awaismslm avatar max-ipinfo avatar maxmouchet avatar rm-umar avatar shamirshahzad avatar st-polina avatar taimoor-12 avatar umanshahzad avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mmdbctl's Issues

Memory Issue

So I have been playing around with mmdbctl and I was doing simple mmdb export to json and import back to mmdb. However, the process started taking up to 46 GB of memory. Luckily my machine had plenty of memory so import was successful. However, systems with low memory may run into problems.

I did some digging into source and found that mmdbctl is holding all data into memory and writing into file at once after processing is done. Can we do buffered writing and flush incrementally to prevent huge memory usages?

fmt.Fprintf(os.Stderr, "writing to %s (%v entries)\n", f.Out, entrycnt)

Task Manager:

Screenshot 2024-02-08 161631

MMDB file used: GeoLite2-City.mmdb

File extensions not triggering default flags in import

According to mmdbctl import help the file extensions should trigger the default flag

    -t, --tsv
      interpret input file as TSV.
      by default, the .tsv extension will turn this on.

but it's giving error if we don't specify the flag explicitly

$ mmdbctl import abc.csv 
err: input file type unknown

Giving error on json and csv as well

is ipapi csv's conversion supported?

i want to use the csv DB file from https://ipapi.is/developers.html#geolocation-database but when i try to convert it with:
mmdbctl import --in geolocationDatabaseIPv4.csv --out data.mmdb
i get error:
err: couldn't parse cidr "4/32": invalid CIDR address: 4/32

Why is it giving this error?
Is it possible you can see if you can make this conversion for ipapi csv's compatible with mmdbctl?

thanks in advance

ps: surprised no-one has mentioned ipapi.is db's

Compatibility issue with IP2Location DB which uses int format for ip address range start and end

Command: mmdbctl import -c --in IP2LOCATION-LITE-DB3.CSV --out IP2LOCATION-LITE-DB3.mmdb
Output: err: couldn't parse cidr "16777216/32": invalid CIDR address: 16777216/32

IP2LOCATION-LITE-DB3.CSV file format:

"0","16777215","-","-","-","-"
"16777216","16777471","US","United States of America","California","San Jose"
"16777472","16778239","CN","China","Fujian","Fuzhou"
"16778240","16778495","AU","Australia","Tasmania","Glebe"
"16778496","16779263","AU","Australia","Victoria","Melbourne"
"16779264","16781311","CN","China","Guangdong","Guangzhou"
"16781312","16785407","JP","Japan","Tokyo","Tokyo"

Granular data section metadata

As an extension to #25 it'd be nice to see not only data-section-size, but also a breakdown of the size of individual data types within that data section (e.g. string, pointer, int, map, etc).

MMDB with nested structures break read and export

When attempting to use this project to export from an mmdb with nested objects it throws an error: err: failed to get record for next subnet: maxminddb: cannot unmarshal map into type string. The read operation also fails with an error: err: couldn't get data for <requested_ip>.

In both these cases it seems to stem from the assumption that records are a map[string]string instead of map[string]interface{}. Unfortunately that opens up a new host of problems with representation in output formats incapable of nested structures natively like csv/tsv.

file size difference

GeoLite2-City.mmdb(64.2 MB) export to city.json(4.53 GB)
city.json(4.53 GB) import city.mmdb(287 MB)

Why is the re exported file(city.mmdb(287 MB)) much larger than the original(GeoLite2-City.mmdb(64.2 MB))

Am I missing any parameters.

Support for merging mmdb or csv files?

Is it supported to merge two mmdb or csv files that record different information?

For example, one is an mmdb or csv file that records country information, and the other is a file that records ASN. Is it possible to merge these two files into one that contains both ASN and country information, just like the three free databases you provide officially?

If it is possible to implement, can you give me an example of a specific command? If it is not possible to implement temporarily, is it possible to implement it in the future?

Low-level data about MMDB

Hey @UmanShahzad.

To make mmdbctl even more awesome, it would be great to be able to display some low-level data about an MMDB file, such as

  • Tree size in bytes
  • Data section start/end offsets
  • Data section size in bytes
  • Metadata section start offset

This is helpful, for example, if you want to inspect (with hexdump) the actual data section, or if you want to estimate relative impact of the tree/data sections to file size.

Simple example. Let's say we want to find out whether the actual MMDB writer deduplicates written objects (replaces by pointers) or not. I'll use my MMDB parser to display abovementioned offsets.

  • Case 1 -- write two different objects
$ echo -e '{"range":"1.0.0.0/24","value":{"col":"nested1"}}\n{"range":"2.0.0.0/24", "value":{"col":"nested2"}}' | mmdbctl import --no-network -j -o test.mmdb
writing to test.mmdb (2 entries)

$ python3 ./parser.py  test.mmdb
Namespace(file='test.mmdb', meta=False, data=None, ip=None)
Data section offset 1096 (data starts at 1112)  # <===
Metadata section offset: 1146 (metadata starts at 1160)
Data section size 34 bytes (3.4e-05 MB)  # <===
Record size: 32
Node count: 137
Tree size: 1096 (bytes)
ip_version: 6
First data record at 153 pointer

# Knowing the offset/size, we can inspect specific portion of the file:
$ hd -s 1112 -n 34 test.mmdb
00000458  e1 45 76 61 6c 75 65 e1  43 63 6f 6c 47 6e 65 73  |.Evalue.CcolGnes|
00000468  74 65 64 31 e1 20 01 e1  20 08 47 6e 65 73 74 65  |ted1. .. .Gneste|
00000478  64 32                                             |d2|
0000047a
  • Case 2 -- write duplicate objects:
$ echo -e '{"range":"1.0.0.0/24","value":{"col":"nested1"}}\n{"range":"2.0.0.0/24", "value":{"col":"nested1"}}' | mmdbctl import --no-network -j -o test.mmdb
writing to test.mmdb (2 entries)

$ python3 ./parser.py  test.mmdb
Namespace(file='test.mmdb', meta=False, data=None, ip=None)
Data section offset 1096 (data starts at 1112)  # <===
Metadata section offset: 1132 (metadata starts at 1146)
Data section size 20 bytes (2e-05 MB)   # <===
Record size: 32
Node count: 137
Tree size: 1096 (bytes)
ip_version: 6
First data record at 153 pointer

$ hd -s 1112 -n 20 test.mmdb
00000458  e1 45 76 61 6c 75 65 e1  43 63 6f 6c 47 6e 65 73  |.Evalue.CcolGnes|
00000468  74 65 64 31                                       |ted1|   # Note it removed whole second object and tree points directly to the first one
0000046c

So it does deduplicate objects. Looks like it even deduplicates nested objects, which is great.

The point is it is really convenient to know those offsets when doing stuff like this.

Not sure if Go MMDB reader exposes this data, but it should be easy to find section separators (see the specs) even without parsing the file, e.g. by mmap-ing the file and using string search functions: https://github.com/svbatalov/construct_mmdb_parser/blob/11b13ef946b7d85cec4e21a538af49b5b44f22a1/parser.py#L13-L19

Thanks,
Sergey

Compatibility with maxmind datasets

For some reason mmdctl doesn't work with maxmind's geoip and geolite datasets: all requests for any ip return err: couldn't get data for x.x.x.x.

mmdbctl read -f json-pretty 8.8.8.8 ./GeoLite2-Country.mmdb 
err: couldn't get data for 8.8.8.8

mmdbctl read -f json-pretty 1.1.1.0/31 ./GeoIP2-Country.mmdb
err: couldn't get data for 1.1.1.0
err: couldn't get data for 1.1.1.1

ipinfo dataset works fine:

mmdbctl read -f json-pretty 8.8.8.8 ./Ipinfo-Country.mmdb 
{
  "continent": "NA",
  "continent_name": "North America",
  "country": "US",
  "country_name": "United States"
}

Metadata:

mmdbctl metadata ./GeoIP2-Country.mmdb 
- Binary Format 2.0
- Database Type GeoIP2-Country
- IP Version    6
- Record Size   24
- Node Count    1201540
- Description   
    en GeoIP2 Country database
- Languages     de, en, es, fr, ja, pt-BR, ru, zh-CN
- Build Epoch   1647287311

Is it possible to make them work together?

panic: runtime error on iplocation.mmdb

Hello,
I am running errors using mmdbctl_1.4.4_linux_386 verify with iplocation.mmdb (e.g. standard_location.mmdb)
Maybe it's related to the important size of the mmdb ?

./mmdbctl_1.4.4_linux_386 verify iplocation.mmdb
panic: runtime error: index out of range [654620380] with length 654620376

goroutine 1 [running]:
github.com/oschwald/maxminddb-golang.nodeReader32.readRight(...)
        /home/runner/go/pkg/mod/github.com/oschwald/[email protected]/node.go:54
github.com/oschwald/maxminddb-golang.(*Networks).Next(0x9c50090)
        /home/runner/go/pkg/mod/github.com/oschwald/[email protected]/traverse.go:142 +0x195
github.com/oschwald/maxminddb-golang.(*verifier).verifySearchTree(0x9c56f08)
        /home/runner/go/pkg/mod/github.com/oschwald/[email protected]/verifier.go:106 +0x7e
github.com/oschwald/maxminddb-golang.(*verifier).verifyDatabase(0x9c56f08)
        /home/runner/go/pkg/mod/github.com/oschwald/[email protected]/verifier.go:90 +0x25
github.com/oschwald/maxminddb-golang.(*Reader).Verify(0x9c00180)
        /home/runner/go/pkg/mod/github.com/oschwald/[email protected]/verifier.go:21 +0x51
github.com/ipinfo/mmdbctl/lib.CmdVerify({0x0}, {0x9c10438, 0x1, 0x1}, 0x825e31c)
        /home/runner/work/mmdbctl/mmdbctl/lib/cmd_verify.go:49 +0x142
main.cmdVerify()
        /home/runner/work/mmdbctl/mmdbctl/cmd_verify.go:35 +0x100
main.main()
        /home/runner/work/mmdbctl/mmdbctl/main.go:42 +0x141

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.