Skip to content

Commit

Permalink
Add mmdbquery util
Browse files Browse the repository at this point in the history
  • Loading branch information
dhaavi committed Dec 5, 2023
1 parent 2d3faed commit ee55b79
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Binaries
cmd/mmdbmeld/mmdbmeld
cmd/mmdbcheck/mmdbcheck
cmd/mmdbquery/mmdbquery

# Input
input/**.csv
Expand All @@ -10,3 +11,6 @@ input/**.etag

# Output
output/*

# Dev files
config.yml
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ __Step 1: Compile__

$ go build -C cmd/mmdbmeld
$ go build -C cmd/mmdbcheck
$ go build -C cmd/mmdbquery

__Step 2: Download geoip data sources__

Expand Down Expand Up @@ -107,6 +108,16 @@ This check queries the following fields:
- SP: `is_satellite_provider`
- AP: `is_anonymous_proxy`

__Step 5: Query your MMDBs__

$ ./cmd/mmdbquery/mmdbquery output/geoip-v4.mmdb 1.1.1.1

1.1.1.0/24:
autonomous_system_number: 13335
autonomous_system_organization: Cloudflare, Inc.
country:
iso_code: AU

### Customize your MMDBs.

Take a look at the <config-example.yml> to get an idea how to customize your MMDB.
Expand Down
86 changes: 86 additions & 0 deletions cmd/mmdbquery/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package main

import (
"fmt"
"net"
"os"
"slices"
"strings"

reader "github.com/oschwald/maxminddb-golang"
)

func main() {
if len(os.Args) < 3 {
fmt.Printf("usage: %s <mmdb> <IPs>\n", os.Args[0])
os.Exit(1)
}

r, err := reader.Open(os.Args[1])
if err != nil {
fmt.Printf("error: failed to open mmdb file: %s\n", err)
os.Exit(2)
}

for i, ipArg := range os.Args[2:] {
// Add a space after first result.
if i > 0 {
fmt.Println()
}

// Parse IP.
ip := net.ParseIP(ipArg)
if ip == nil {
fmt.Printf("error: invalid IP: %s\n", ipArg)
os.Exit(2)
}

// Get data of IP.
anyData := make(map[string]any)
recordNet, ok, err := r.LookupNetwork(ip, &anyData)
if err != nil {
fmt.Printf("error: failed to lookup IP: %s\n", err)
os.Exit(4)
}
if !ok {
fmt.Printf("error: database does not have a record for %s\n", ip)
}

// Print result.
fmt.Printf("%s:\n", recordNet)
printData(anyData, " ")
}
}

type keyValue struct {
key string
value any
}

func printData(m map[string]any, indent string) {
// Order data.
ordered := make([]keyValue, 0, len(m))
for k, v := range m {
ordered = append(ordered, keyValue{
key: k,
value: v,
})
}
slices.SortFunc[[]keyValue, keyValue](
ordered,
func(a, b keyValue) int {
return strings.Compare(a.key, b.key)
},
)

// Print ordered data.
for _, e := range ordered {
subMap, ok := e.value.(map[string]any)
if ok {
fmt.Printf("%s%s:\n", indent, e.key)
printData(subMap, indent+" ")
} else {
fmt.Printf("%s%s: %v\n", indent, e.key, e.value)
}
}
}

0 comments on commit ee55b79

Please sign in to comment.