first commit
This commit is contained in:
commit
7181502a64
11 changed files with 770 additions and 0 deletions
136
geo.go
Normal file
136
geo.go
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/oschwald/maxminddb-golang"
|
||||
)
|
||||
|
||||
type Geo struct {
|
||||
asn *maxminddb.Reader
|
||||
city *maxminddb.Reader
|
||||
}
|
||||
|
||||
type ASNResult struct {
|
||||
AutonomousSystemNumber uint `maxminddb:"autonomous_system_number"`
|
||||
AutonomousSystemOrganization string `maxminddb:"autonomous_system_organization"`
|
||||
}
|
||||
|
||||
type CityResult struct {
|
||||
Continent struct {
|
||||
Names map[string]string `maxminddb:"names"`
|
||||
} `maxminddb:"continent"`
|
||||
Country struct {
|
||||
Names map[string]string `maxminddb:"names"`
|
||||
} `maxminddb:"country"`
|
||||
City struct {
|
||||
Names map[string]string `maxminddb:"names"`
|
||||
} `maxminddb:"city"`
|
||||
}
|
||||
|
||||
func DownloadFile(url, dest string) error {
|
||||
if err := os.MkdirAll(filepath.Dir(dest), 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("downloading %s -> %s\n", url, dest)
|
||||
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("HTTP %d for %s", resp.StatusCode, url)
|
||||
}
|
||||
|
||||
out, err := os.Create(dest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
_, err = io.Copy(out, resp.Body)
|
||||
return err
|
||||
}
|
||||
|
||||
func ensureMMDB(url, path string) error {
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
return nil
|
||||
}
|
||||
return DownloadFile(url, path)
|
||||
}
|
||||
|
||||
func InitGeo(cfg *GeoConfig) (*Geo, error) {
|
||||
if err := ensureMMDB(cfg.AsnURL, cfg.AsnPath); err != nil {
|
||||
return nil, fmt.Errorf("ASN DB: %w", err)
|
||||
}
|
||||
if err := ensureMMDB(cfg.CityURL, cfg.CityPath); err != nil {
|
||||
return nil, fmt.Errorf("City DB: %w", err)
|
||||
}
|
||||
|
||||
asn, err := maxminddb.Open(cfg.AsnPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open ASN DB: %w", err)
|
||||
}
|
||||
city, err := maxminddb.Open(cfg.CityPath)
|
||||
if err != nil {
|
||||
asn.Close()
|
||||
return nil, fmt.Errorf("open City DB: %w", err)
|
||||
}
|
||||
|
||||
return &Geo{asn: asn, city: city}, nil
|
||||
}
|
||||
|
||||
func (g *Geo) Close() {
|
||||
g.asn.Close()
|
||||
g.city.Close()
|
||||
}
|
||||
|
||||
type GeoInfo struct {
|
||||
ASN string
|
||||
Org string
|
||||
Continent string
|
||||
Country string
|
||||
City string
|
||||
ReverseDNS string
|
||||
}
|
||||
|
||||
func (g *Geo) Lookup(ip net.IP) GeoInfo {
|
||||
info := GeoInfo{ReverseDNS: "Unknown"}
|
||||
|
||||
hosts, err := net.LookupAddr(ip.String())
|
||||
if err == nil && len(hosts) > 0 {
|
||||
info.ReverseDNS = hosts[0]
|
||||
}
|
||||
|
||||
var asn ASNResult
|
||||
if err := g.asn.Lookup(ip, &asn); err == nil {
|
||||
if asn.AutonomousSystemNumber > 0 {
|
||||
info.ASN = fmt.Sprintf("AS%d", asn.AutonomousSystemNumber)
|
||||
info.Org = asn.AutonomousSystemOrganization
|
||||
}
|
||||
}
|
||||
|
||||
var cr CityResult
|
||||
if err := g.city.Lookup(ip, &cr); err == nil {
|
||||
info.Continent = cr.Continent.Names["en"]
|
||||
info.Country = cr.Country.Names["en"]
|
||||
info.City = cr.City.Names["en"]
|
||||
}
|
||||
|
||||
return info
|
||||
}
|
||||
|
||||
type GeoConfig struct {
|
||||
AsnURL string
|
||||
CityURL string
|
||||
AsnPath string
|
||||
CityPath string
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue