feat: use ripedb for asn lookup
This commit is contained in:
parent
59cefcdf67
commit
f22e3a4bad
7 changed files with 230 additions and 36 deletions
126
ripe/builder.go
Normal file
126
ripe/builder.go
Normal file
|
@ -0,0 +1,126 @@
|
|||
package ripe
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"compress/gzip"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/maxmind/mmdbwriter"
|
||||
"github.com/maxmind/mmdbwriter/mmdbtype"
|
||||
)
|
||||
|
||||
type MMDBEntry struct {
|
||||
Range string `json:"range",maxminddb:"range"`
|
||||
ASN string `json:"asn",maxminddb:"asn"`
|
||||
}
|
||||
|
||||
const (
|
||||
ripe4_download_url = "https://ftp.ripe.net/ripe/dbase/split/ripe.db.route.gz"
|
||||
ripe6_download_url = "https://ftp.ripe.net/ripe/dbase/split/ripe.db.route6.gz"
|
||||
)
|
||||
|
||||
func BuildNewMMDB(filepath string) error {
|
||||
writer, err := mmdbwriter.New(
|
||||
mmdbwriter.Options{
|
||||
DatabaseType: "VOC-ASN-DB",
|
||||
RecordSize: 32,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating mmdb writer: %w", err)
|
||||
}
|
||||
|
||||
if err := fillMMDB(writer, ripe4_download_url); err != nil {
|
||||
return fmt.Errorf("error building IPv4 mmdb: %w", err)
|
||||
}
|
||||
|
||||
if err := fillMMDB(writer, ripe6_download_url); err != nil {
|
||||
return fmt.Errorf("error building IPv6 mmdb: %w", err)
|
||||
}
|
||||
|
||||
fh, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating mmdb output file: %w", err)
|
||||
}
|
||||
|
||||
if _, err = writer.WriteTo(fh); err != nil {
|
||||
return fmt.Errorf("error writing mmdb to file: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func fillMMDB(mmdb *mmdbwriter.Tree, url string) error {
|
||||
// Fetch data from URL
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error fetching data from %s: %w", url, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var s *bufio.Scanner
|
||||
|
||||
// Check if response is gzip compressed
|
||||
reader, err := gzip.NewReader(resp.Body)
|
||||
if err != nil {
|
||||
s = bufio.NewScanner(resp.Body)
|
||||
} else {
|
||||
s = bufio.NewScanner(reader)
|
||||
defer reader.Close()
|
||||
}
|
||||
|
||||
var (
|
||||
entries []MMDBEntry
|
||||
entry MMDBEntry
|
||||
)
|
||||
|
||||
for tok := s.Scan(); tok; tok = s.Scan() {
|
||||
//remove all spaces
|
||||
line := strings.ReplaceAll(s.Text(), " ", "")
|
||||
|
||||
tokens := strings.Split(line, ":")
|
||||
|
||||
if len(tokens) != 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
key := strings.TrimSpace(tokens[0])
|
||||
if key == "route" {
|
||||
entry = MMDBEntry{
|
||||
Range: strings.TrimSpace(tokens[1]),
|
||||
}
|
||||
} else if key == "origin" {
|
||||
entry.ASN = strings.TrimSpace(tokens[1])
|
||||
entries = append(entries, entry)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if err := s.Err(); err != nil {
|
||||
fmt.Printf("error scanning ripe file: %s", err)
|
||||
}
|
||||
|
||||
var entrieErrors error
|
||||
for _, e := range entries {
|
||||
record := mmdbtype.Map{
|
||||
"range": mmdbtype.String(e.Range),
|
||||
"asn": mmdbtype.String(e.ASN),
|
||||
}
|
||||
|
||||
_, network, err := net.ParseCIDR(e.Range)
|
||||
if err != nil {
|
||||
errors.Join(entrieErrors, fmt.Errorf("error parsing CIDR: %w", err))
|
||||
continue
|
||||
}
|
||||
|
||||
err = mmdb.Insert(network, record)
|
||||
errors.Join(entrieErrors, fmt.Errorf("error inserting record: %w", err))
|
||||
}
|
||||
|
||||
return entrieErrors
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue