mirror of https://github.com/mpolden/echoip
Added ASN
This commit is contained in:
parent
ab37be0fd4
commit
f77fb4fbc0
|
@ -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)
|
||||
}
|
||||
|
|
21
http/http.go
21
http/http.go
|
@ -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 {
|
||||
|
@ -52,13 +54,21 @@ func New(db database.Client) *Server {
|
|||
|
||||
func ipFromRequest(header string, r *http.Request) (net.IP, error) {
|
||||
remoteIP := r.Header.Get(header)
|
||||
if remoteIP == "" && r.URL != nil {
|
||||
host := filepath.Base(r.URL.Path)
|
||||
ip := net.ParseIP(host)
|
||||
if ip != nil {
|
||||
remoteIP = ip.String()
|
||||
}
|
||||
fmt.Printf("IP: %v\n", ip)
|
||||
}
|
||||
if remoteIP == "" {
|
||||
host, _, err := net.SplitHostPort(r.RemoteAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
remoteIP = host
|
||||
}
|
||||
fmt.Printf("Remote: %v\n", remoteIP)
|
||||
ip := net.ParseIP(remoteIP)
|
||||
if ip == nil {
|
||||
return nil, fmt.Errorf("could not parse IP: %s", remoteIP)
|
||||
|
@ -74,10 +84,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 +103,8 @@ func (s *Server) newResponse(r *http.Request) (Response, error) {
|
|||
Hostname: hostname,
|
||||
LocationLatitude: city.Latitude,
|
||||
LocationLongitude: city.Longitude,
|
||||
AutonomousSystemNumber: autonomousSystemNumber,
|
||||
AutonomousSystemOrganization: asn.AutonomousSystemOrganization,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -264,6 +281,8 @@ func (s *Server) Handler() http.Handler {
|
|||
r.Route("GET", "/", s.JSONHandler).Header("Accept", jsonMediaType)
|
||||
r.Route("GET", "/json", s.JSONHandler)
|
||||
|
||||
r.RoutePrefix("GET", "/json/", s.JSONHandler)
|
||||
|
||||
// CLI
|
||||
r.Route("GET", "/", s.CLIHandler).MatcherFunc(cliMatcher)
|
||||
r.Route("GET", "/", s.CLIHandler).Header("Accept", textMediaType)
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue