From 81aa4847624717f28a5592f972afb58729d92a23 Mon Sep 17 00:00:00 2001 From: Ethan Knowlton Date: Sat, 30 Sep 2023 11:17:44 -0400 Subject: [PATCH 1/2] Added extra IP Stack fields - IsDaylightSavings - IsProxy - IsTOR - IsCrawler - CrawlerName - CrawlerType - ThreatLevel - ThreatTypes --- html/index.html | 52 ++++++++++++++++++++++++++++++++++++++- iputil/ipstack/ipstack.go | 11 +++++++++ iputil/paser/parser.go | 47 +++++++++++++++++++++-------------- 3 files changed, 90 insertions(+), 20 deletions(-) diff --git a/html/index.html b/html/index.html index 80415922..6cf51115 100644 --- a/html/index.html +++ b/html/index.html @@ -136,6 +136,11 @@

What do we know about this IP address?

Timezone {{ .Timezone }} + {{ end }} {{ if .IsDayLightSavings }} + + Is Daylight Savings? + {{ .IsDayLightSavings }} + {{ end }} {{ if .ASN }} ASN @@ -166,7 +171,52 @@

What do we know about this IP address?

User agent: Raw {{ .UserAgent.RawValue }} - {{ end }} {{ end }} + {{ end }} + + {{ if .IsProxy }} + + Is Proxy? + {{ .IsProxy }} + + {{ end }} + + {{ if .IsCrawler }} + + Is Crawler? + {{ .IsCrawler }} + + + Crawler Name + {{ .CrawlerName }} + + + Crawler Type + {{ .CrawlerType }} + + {{ end }} + + {{ if .IsTor }} + + Is Tor? + {{ .IsTor }} + + {{ end }} + + {{ if .ThreatLevel }} + + Threat Level + {{ .ThreatLevel }} + + {{ end }} + + {{ if .ThreatTypes }} + + Threat Types + {{ .ThreatTypes }} + + {{ end }} + + {{ end }} {{ if .Country }} {{ if .UsingGeoIP }}

diff --git a/iputil/ipstack/ipstack.go b/iputil/ipstack/ipstack.go index ce8383e1..44f80c7c 100644 --- a/iputil/ipstack/ipstack.go +++ b/iputil/ipstack/ipstack.go @@ -41,6 +41,17 @@ func (ips *IPStack) Parse(ip net.IP, hostname string) (parser.Response, error) { if res.Timezone != nil { parserResponse.Timezone = res.Timezone.ID + parserResponse.IsDayLightSavings = res.Timezone.IsDaylightSaving + } + + if res.Security != nil { + parserResponse.IsProxy = res.Security.IsProxy + parserResponse.IsCrawler = res.Security.IsCrawler + parserResponse.CrawlerName = res.Security.CrawlerName + parserResponse.CrawlerType = res.Security.CrawlerType + parserResponse.IsTor = res.Security.IsTOR + parserResponse.ThreatLevel = res.Security.ThreatLevel + parserResponse.ThreatTypes = &res.Security.ThreatTypes } if res.Location != nil { diff --git a/iputil/paser/parser.go b/iputil/paser/parser.go index 4cf731ad..92ca9ee2 100644 --- a/iputil/paser/parser.go +++ b/iputil/paser/parser.go @@ -13,23 +13,32 @@ type Parser interface { } type Response struct { - UsingGeoIP bool `json:"UsingGeoIP"` - UsingIPStack bool `json:"UsingIPStack"` - IP net.IP `json:"ip"` - IPDecimal *big.Int `json:"ip_decimal"` - Country string `json:"country,omitempty"` - CountryISO string `json:"country_iso,omitempty"` - CountryEU *bool `json:"country_eu,omitempty"` - RegionName string `json:"region_name,omitempty"` - RegionCode string `json:"region_code,omitempty"` - MetroCode uint `json:"metro_code,omitempty"` - PostalCode string `json:"zip_code,omitempty"` - City string `json:"city,omitempty"` - Latitude float64 `json:"latitude,omitempty"` - Longitude float64 `json:"longitude,omitempty"` - Timezone string `json:"time_zone,omitempty"` - ASN string `json:"asn,omitempty"` - ASNOrg string `json:"asn_org,omitempty"` - Hostname string `json:"hostname,omitempty"` - UserAgent *useragent.UserAgent `json:"user_agent,omitempty"` + UsingGeoIP bool `json:"UsingGeoIP"` + UsingIPStack bool `json:"UsingIPStack"` + IP net.IP `json:"ip"` + IPDecimal *big.Int `json:"ip_decimal"` + Country string `json:"country,omitempty"` + CountryISO string `json:"country_iso,omitempty"` + CountryEU *bool `json:"country_eu,omitempty"` + RegionName string `json:"region_name,omitempty"` + RegionCode string `json:"region_code,omitempty"` + MetroCode uint `json:"metro_code,omitempty"` + PostalCode string `json:"zip_code,omitempty"` + City string `json:"city,omitempty"` + Latitude float64 `json:"latitude,omitempty"` + Longitude float64 `json:"longitude,omitempty"` + Timezone string `json:"time_zone,omitempty"` + IsDayLightSavings bool `json:"is_daylight_savings,omitempty"` + ASN string `json:"asn,omitempty"` + ASNOrg string `json:"asn_org,omitempty"` + Hostname string `json:"hostname,omitempty"` + UserAgent *useragent.UserAgent `json:"user_agent,omitempty"` + CurrencyCode string `json:"currency_code,omitempty"` + IsProxy bool `json:"is_proxy,omitempty"` + IsCrawler bool `json:"is_crawler,omitempty"` + CrawlerName string `json:"crawler_name,omitempty"` + CrawlerType string `json:"crawler_type,omitempty"` + IsTor bool `json:"is_tor,omitempty"` + ThreatLevel string `json:"threat_level,omitempty"` + ThreatTypes *interface{} `json:"threat_types,omitempty"` } From 410002ff47abc67c3b931c38a449d2f098958761 Mon Sep 17 00:00:00 2001 From: Ethan Knowlton Date: Wed, 4 Oct 2023 09:43:37 -0400 Subject: [PATCH 2/2] upadted template, added https option for ipstack --- cmd/echoip/main.go | 15 ++++++++++- html/index.html | 16 +++-------- http/http_test.go | 4 +-- iputil/geo/geo.go | 37 ++++++++++++------------- iputil/ipstack/ipstack.go | 7 ++++- iputil/paser/parser.go | 57 ++++++++++++++++++++------------------- 6 files changed, 74 insertions(+), 62 deletions(-) diff --git a/cmd/echoip/main.go b/cmd/echoip/main.go index e66ca70e..7c0a6688 100644 --- a/cmd/echoip/main.go +++ b/cmd/echoip/main.go @@ -35,6 +35,8 @@ func main() { var ipstackApiKey string service := flag.String("d", "geoip", "Which database to use, 'ipstack' or 'geoip'") flag.StringVar(&ipstackApiKey, "S", "", "IP Stack API Key") + ipStackEnableSecurityModule := flag.Bool("x", false, "Enable security module for IP Stack ( must have security module, aka. non-free account. )") + ipStackUseHttps := flag.Bool("h", false, "Use HTTPS for IP Stack ( only non-free accounts )") countryFile := flag.String("f", "", "Path to GeoIP country database") cityFile := flag.String("c", "", "Path to GeoIP city database") asnFile := flag.String("a", "", "Path to GeoIP ASN database") @@ -56,6 +58,7 @@ func main() { var parser parser.Parser if *service == "geoip" { + log.Print("Using GeoIP for IP database") geo, err := geo.Open(*countryFile, *cityFile, *asnFile) if err != nil { log.Fatal(err) @@ -64,7 +67,17 @@ func main() { } if *service == "ipstack" { - if err := ipstackApi.Init(ipstackApiKey); err != nil { + log.Print("Using GeoIP for IP database") + if *ipStackEnableSecurityModule { + log.Print("Enable Security Module ( Requires Professional Plus account )") + } + enableSecurity := ipstackApi.ParamEnableSecurity(*ipStackEnableSecurityModule) + apiKey := ipstackApi.ParamToken(ipstackApiKey) + useHttps := ipstackApi.ParamUseHTTPS(*ipStackUseHttps) + if *ipStackUseHttps { + log.Print("Use IP Stack HTTPS API ( Requires non-free account )") + } + if err := ipstackApi.Init(apiKey, enableSecurity, useHttps); err != nil { log.Fatal(err) } ips := ipstack.IPStack{} diff --git a/html/index.html b/html/index.html index 6cf51115..9657acb6 100644 --- a/html/index.html +++ b/html/index.html @@ -173,18 +173,17 @@

What do we know about this IP address?

{{ end }} - {{ if .IsProxy }} + {{ if .IPStackSecurityEnabled }} Is Proxy? {{ .IsProxy }} - {{ end }} - - {{ if .IsCrawler }} Is Crawler? {{ .IsCrawler }} + + {{ if .IsCrawler }} Crawler Name {{ .CrawlerName }} @@ -193,23 +192,16 @@

What do we know about this IP address?

Crawler Type {{ .CrawlerType }} - {{ end }} + {{ end }} - {{ if .IsTor }} Is Tor? {{ .IsTor }} - {{ end }} - - {{ if .ThreatLevel }} Threat Level {{ .ThreatLevel }} - {{ end }} - - {{ if .ThreatTypes }} Threat Types {{ .ThreatTypes }} diff --git a/http/http_test.go b/http/http_test.go index 29a97be6..b6216452 100644 --- a/http/http_test.go +++ b/http/http_test.go @@ -163,7 +163,7 @@ func TestDisabledHandlers(t *testing.T) { {s.URL + "/country", "404 page not found", 404}, {s.URL + "/country-iso", "404 page not found", 404}, {s.URL + "/city", "404 page not found", 404}, - {s.URL + "/json", "{\n \"UsingGeoIP\": true,\n \"UsingIPStack\": false,\n \"ip\": \"127.0.0.1\",\n \"ip_decimal\": 2130706433\n}", 200}, + {s.URL + "/json", "{\n \"UsingGeoIP\": true,\n \"UsingIPStack\": false,\n \"IPStackSecurityEnabled\": false,\n \"ip\": \"127.0.0.1\",\n \"ip_decimal\": 2130706433\n}", 200}, } for _, tt := range tests { @@ -189,7 +189,7 @@ func TestJSONHandlers(t *testing.T) { out string status int }{ - {s.URL, "{\n \"UsingGeoIP\": true,\n \"UsingIPStack\": false,\n \"ip\": \"127.0.0.1\",\n \"ip_decimal\": 2130706433,\n \"country\": \"Elbonia\",\n \"country_iso\": \"EB\",\n \"country_eu\": false,\n \"region_name\": \"North Elbonia\",\n \"region_code\": \"1234\",\n \"metro_code\": 1234,\n \"zip_code\": \"1234\",\n \"city\": \"Bornyasherk\",\n \"latitude\": 63.416667,\n \"longitude\": 10.416667,\n \"time_zone\": \"Europe/Bornyasherk\",\n \"asn\": \"AS59795\",\n \"asn_org\": \"Hosting4Real\",\n \"hostname\": \"localhost\",\n \"user_agent\": {\n \"product\": \"curl\",\n \"version\": \"7.2.6.0\",\n \"raw_value\": \"curl/7.2.6.0\"\n }\n}", 200}, + {s.URL, "{\n \"UsingGeoIP\": true,\n \"UsingIPStack\": false,\n \"IPStackSecurityEnabled\": false,\n \"ip\": \"127.0.0.1\",\n \"ip_decimal\": 2130706433,\n \"country\": \"Elbonia\",\n \"country_iso\": \"EB\",\n \"country_eu\": false,\n \"region_name\": \"North Elbonia\",\n \"region_code\": \"1234\",\n \"metro_code\": 1234,\n \"zip_code\": \"1234\",\n \"city\": \"Bornyasherk\",\n \"latitude\": 63.416667,\n \"longitude\": 10.416667,\n \"time_zone\": \"Europe/Bornyasherk\",\n \"asn\": \"AS59795\",\n \"asn_org\": \"Hosting4Real\",\n \"hostname\": \"localhost\",\n \"user_agent\": {\n \"product\": \"curl\",\n \"version\": \"7.2.6.0\",\n \"raw_value\": \"curl/7.2.6.0\"\n }\n}", 200}, {s.URL + "/port/foo", "{\n \"status\": 400,\n \"error\": \"invalid port: foo\"\n}", 400}, {s.URL + "/port/0", "{\n \"status\": 400,\n \"error\": \"invalid port: 0\"\n}", 400}, {s.URL + "/port/65537", "{\n \"status\": 400,\n \"error\": \"invalid port: 65537\"\n}", 400}, diff --git a/iputil/geo/geo.go b/iputil/geo/geo.go index 0f97a6b1..fdacf2c3 100644 --- a/iputil/geo/geo.go +++ b/iputil/geo/geo.go @@ -81,24 +81,25 @@ func (g *geoip) Parse(ip net.IP, hostname string) (parser.Response, error) { autonomousSystemNumber = fmt.Sprintf("AS%d", asn.AutonomousSystemNumber) } return parser.Response{ - UsingGeoIP: true, - UsingIPStack: false, - IP: ip, - IPDecimal: ipDecimal, - Country: country.Name, - CountryISO: country.ISO, - CountryEU: country.IsEU, - RegionName: city.RegionName, - RegionCode: city.RegionCode, - MetroCode: city.MetroCode, - PostalCode: city.PostalCode, - City: city.Name, - Latitude: city.Latitude, - Longitude: city.Longitude, - Timezone: city.Timezone, - ASN: autonomousSystemNumber, - ASNOrg: asn.AutonomousSystemOrganization, - Hostname: hostname, + UsingGeoIP: true, + UsingIPStack: false, + IPStackSecurityEnabled: false, + IP: ip, + IPDecimal: ipDecimal, + Country: country.Name, + CountryISO: country.ISO, + CountryEU: country.IsEU, + RegionName: city.RegionName, + RegionCode: city.RegionCode, + MetroCode: city.MetroCode, + PostalCode: city.PostalCode, + City: city.Name, + Latitude: city.Latitude, + Longitude: city.Longitude, + Timezone: city.Timezone, + ASN: autonomousSystemNumber, + ASNOrg: asn.AutonomousSystemOrganization, + Hostname: hostname, }, nil } diff --git a/iputil/ipstack/ipstack.go b/iputil/ipstack/ipstack.go index 44f80c7c..6ec3be5d 100644 --- a/iputil/ipstack/ipstack.go +++ b/iputil/ipstack/ipstack.go @@ -3,6 +3,7 @@ package ipstack import ( "fmt" "net" + "reflect" "github.com/mpolden/echoip/iputil" parser "github.com/mpolden/echoip/iputil/paser" @@ -45,13 +46,17 @@ func (ips *IPStack) Parse(ip net.IP, hostname string) (parser.Response, error) { } if res.Security != nil { + parserResponse.IPStackSecurityEnabled = true parserResponse.IsProxy = res.Security.IsProxy parserResponse.IsCrawler = res.Security.IsCrawler parserResponse.CrawlerName = res.Security.CrawlerName parserResponse.CrawlerType = res.Security.CrawlerType parserResponse.IsTor = res.Security.IsTOR parserResponse.ThreatLevel = res.Security.ThreatLevel - parserResponse.ThreatTypes = &res.Security.ThreatTypes + + if !reflect.ValueOf(&res.Security.ThreatTypes).IsNil() { + parserResponse.ThreatTypes = &res.Security.ThreatTypes + } } if res.Location != nil { diff --git a/iputil/paser/parser.go b/iputil/paser/parser.go index 92ca9ee2..3a9635d6 100644 --- a/iputil/paser/parser.go +++ b/iputil/paser/parser.go @@ -13,32 +13,33 @@ type Parser interface { } type Response struct { - UsingGeoIP bool `json:"UsingGeoIP"` - UsingIPStack bool `json:"UsingIPStack"` - IP net.IP `json:"ip"` - IPDecimal *big.Int `json:"ip_decimal"` - Country string `json:"country,omitempty"` - CountryISO string `json:"country_iso,omitempty"` - CountryEU *bool `json:"country_eu,omitempty"` - RegionName string `json:"region_name,omitempty"` - RegionCode string `json:"region_code,omitempty"` - MetroCode uint `json:"metro_code,omitempty"` - PostalCode string `json:"zip_code,omitempty"` - City string `json:"city,omitempty"` - Latitude float64 `json:"latitude,omitempty"` - Longitude float64 `json:"longitude,omitempty"` - Timezone string `json:"time_zone,omitempty"` - IsDayLightSavings bool `json:"is_daylight_savings,omitempty"` - ASN string `json:"asn,omitempty"` - ASNOrg string `json:"asn_org,omitempty"` - Hostname string `json:"hostname,omitempty"` - UserAgent *useragent.UserAgent `json:"user_agent,omitempty"` - CurrencyCode string `json:"currency_code,omitempty"` - IsProxy bool `json:"is_proxy,omitempty"` - IsCrawler bool `json:"is_crawler,omitempty"` - CrawlerName string `json:"crawler_name,omitempty"` - CrawlerType string `json:"crawler_type,omitempty"` - IsTor bool `json:"is_tor,omitempty"` - ThreatLevel string `json:"threat_level,omitempty"` - ThreatTypes *interface{} `json:"threat_types,omitempty"` + UsingGeoIP bool `json:"UsingGeoIP"` + UsingIPStack bool `json:"UsingIPStack"` + IPStackSecurityEnabled bool `json:"IPStackSecurityEnabled"` + IP net.IP `json:"ip"` + IPDecimal *big.Int `json:"ip_decimal"` + Country string `json:"country,omitempty"` + CountryISO string `json:"country_iso,omitempty"` + CountryEU *bool `json:"country_eu,omitempty"` + RegionName string `json:"region_name,omitempty"` + RegionCode string `json:"region_code,omitempty"` + MetroCode uint `json:"metro_code,omitempty"` + PostalCode string `json:"zip_code,omitempty"` + City string `json:"city,omitempty"` + Latitude float64 `json:"latitude,omitempty"` + Longitude float64 `json:"longitude,omitempty"` + Timezone string `json:"time_zone,omitempty"` + IsDayLightSavings bool `json:"is_daylight_savings,omitempty"` + ASN string `json:"asn,omitempty"` + ASNOrg string `json:"asn_org,omitempty"` + Hostname string `json:"hostname,omitempty"` + UserAgent *useragent.UserAgent `json:"user_agent,omitempty"` + CurrencyCode string `json:"currency_code,omitempty"` + IsProxy bool `json:"is_proxy,omitempty"` + IsCrawler bool `json:"is_crawler,omitempty"` + CrawlerName string `json:"crawler_name,omitempty"` + CrawlerType string `json:"crawler_type,omitempty"` + IsTor bool `json:"is_tor,omitempty"` + ThreatLevel string `json:"threat_level,omitempty"` + ThreatTypes *interface{} `json:"threat_types,omitempty"` }