Added ASN database

This commit is contained in:
Mike Raunsbæk 2018-06-15 09:31:57 +02:00
parent 7083ff104e
commit 4681914baa
4 changed files with 52 additions and 6 deletions

View File

@ -16,6 +16,7 @@ func main() {
var opts struct {
CountryDBPath string `short:"f" long:"country-db" description:"Path to GeoIP country database" value-name:"FILE" default:""`
CityDBPath string `short:"c" long:"city-db" description:"Path to GeoIP city database" value-name:"FILE" default:""`
ASNDBPath string `short:"a" long:"asn-db" description:"Path to GeoIP ASN database" value-name:"FILE" default:""`
Listen string `short:"l" long:"listen" description:"Listening address" value-name:"ADDR" default:":8080"`
ReverseLookup bool `short:"r" long:"reverse-lookup" description:"Perform reverse hostname lookups"`
PortLookup bool `short:"p" long:"port-lookup" description:"Enable port lookup"`
@ -28,7 +29,7 @@ func main() {
}
log := log.New(os.Stderr, "ipd: ", 0)
db, err := database.New(opts.CountryDBPath, opts.CityDBPath)
db, err := database.New(opts.CountryDBPath, opts.CityDBPath, opts.ASNDBPath)
if err != nil {
log.Fatal(err)
}

View File

@ -38,6 +38,8 @@ type Response struct {
Hostname string `json:"hostname,omitempty"`
LocationLatitude float64 `json:"location_latitude,omitempty"`
LocationLongitude float64 `json:"location_longitude,omitempty"`
AutonomousSystemNumber string `json:"asn_number,omitempty"`
AutonomousSystemOrganization string `json:"asn_organization,omitempty"`
}
type PortResponse struct {
@ -74,10 +76,15 @@ func (s *Server) newResponse(r *http.Request) (Response, error) {
ipDecimal := iputil.ToDecimal(ip)
country, _ := s.db.Country(ip)
city, _ := s.db.City(ip)
asn, _ := s.db.ASN(ip)
var hostname string
if s.LookupAddr != nil {
hostname, _ = s.LookupAddr(ip)
}
var autonomousSystemNumber string
if asn.AutonomousSystemNumber > 0 {
autonomousSystemNumber = "AS" + strconv.FormatUint(uint64(asn.AutonomousSystemNumber), 10);
}
return Response{
IP: ip,
IPDecimal: ipDecimal,
@ -88,6 +95,8 @@ func (s *Server) newResponse(r *http.Request) (Response, error) {
Hostname: hostname,
LocationLatitude: city.Latitude,
LocationLongitude: city.Longitude,
AutonomousSystemNumber: autonomousSystemNumber,
AutonomousSystemOrganization: asn.AutonomousSystemOrganization,
}, nil
}

View File

@ -24,6 +24,10 @@ func (t *testDb) City(net.IP) (database.City, error) {
return database.City{Name: "Bornyasherk"}, nil
}
func (t *testDb) ASN(net.IP) (database.ASN, error) {
return database.ASN{AutonomousSystemNumber: 59795, AutonomousSystemOrganization: "Hosting4Real"}, nil
}
func (t *testDb) IsEmpty() bool { return false }
func testServer() *Server {
@ -90,7 +94,7 @@ func TestDisabledHandlers(t *testing.T) {
server := testServer()
server.LookupPort = nil
server.LookupAddr = nil
server.db, _ = database.New("", "")
server.db, _ = database.New("", "", "")
s := httptest.NewServer(server.Handler())
var tests = []struct {
@ -128,7 +132,7 @@ func TestJSONHandlers(t *testing.T) {
out string
status int
}{
{s.URL, `{"ip":"127.0.0.1","ip_decimal":2130706433,"country":"Elbonia","country_iso":"EB","city":"Bornyasherk","hostname":"localhost"}`, 200},
{s.URL, `{"ip":"127.0.0.1","ip_decimal":2130706433,"country":"Elbonia","country_iso":"EB","city":"Bornyasherk","hostname":"localhost","asn_number":"AS59795","asn_organization":"Hosting4Real"}`, 200},
{s.URL + "/port/foo", `{"error":"Invalid port: 0"}`, 400},
{s.URL + "/port/0", `{"error":"Invalid port: 0"}`, 400},
{s.URL + "/port/65356", `{"error":"Invalid port: 65356"}`, 400},

View File

@ -10,6 +10,7 @@ import (
type Client interface {
Country(net.IP) (Country, error)
City(net.IP) (City, error)
ASN(net.IP) (ASN, error)
IsEmpty() bool
}
@ -25,13 +26,19 @@ type City struct {
Longitude float64
}
type ASN struct {
AutonomousSystemNumber uint
AutonomousSystemOrganization string
}
type geoip struct {
country *geoip2.Reader
city *geoip2.Reader
asn *geoip2.Reader
}
func New(countryDB, cityDB string) (Client, error) {
var country, city *geoip2.Reader
func New(countryDB, cityDB, asnDB string) (Client, error) {
var country, city, asn *geoip2.Reader
if countryDB != "" {
r, err := geoip2.Open(countryDB)
if err != nil {
@ -46,7 +53,14 @@ func New(countryDB, cityDB string) (Client, error) {
}
city = r
}
return &geoip{country: country, city: city}, nil
if asnDB != "" {
r, err := geoip2.Open(asnDB)
if err != nil {
return nil, err
}
asn = r
}
return &geoip{country: country, city: city, asn: asn}, nil
}
func (g *geoip) Country(ip net.IP) (Country, error) {
@ -98,6 +112,24 @@ func (g *geoip) City(ip net.IP) (City, error) {
return city, nil
}
func (g *geoip) ASN(ip net.IP) (ASN, error) {
asn := ASN{}
if g.asn == nil {
return asn, nil
}
record, err := g.asn.ASN(ip)
if err != nil {
return asn, err
}
if record.AutonomousSystemNumber > 0 {
asn.AutonomousSystemNumber = record.AutonomousSystemNumber
}
if record.AutonomousSystemOrganization != "" {
asn.AutonomousSystemOrganization = record.AutonomousSystemOrganization
}
return asn, nil
}
func (g *geoip) IsEmpty() bool {
return g.country == nil && g.city == nil
}