diff --git a/check/check.go b/check/check.go index db0f47f..ffe0915 100644 --- a/check/check.go +++ b/check/check.go @@ -18,6 +18,7 @@ var All = []checkip.Check{ Firehol, IPSum, IPtoASN, + IsOnAWS, MaxMind, OTX, PhishStats, @@ -38,6 +39,7 @@ var Default = []checkip.Check{ Firehol, IPSum, IPtoASN, + IsOnAWS, OTX, Ping, Shodan, diff --git a/check/http.go b/check/http.go index 2cf1a89..6c99c09 100644 --- a/check/http.go +++ b/check/http.go @@ -10,7 +10,7 @@ import ( ) // defaultHttpClient is reused by checks that make HTTP requests. -var defaultHttpClient = newHttpClient(&http.Client{Timeout: 5 * time.Second}) +var defaultHttpClient = newHttpClient(&http.Client{Timeout: 10 * time.Second}) type httpClient struct { client *http.Client diff --git a/check/isonaws.go b/check/isonaws.go new file mode 100644 index 0000000..7b0e1f0 --- /dev/null +++ b/check/isonaws.go @@ -0,0 +1,70 @@ +package check + +import ( + "encoding/json" + "fmt" + "net" + + "github.com/jreisinger/checkip" +) + +type awsIpRanges struct { + IsOn bool + Info struct { + IpPrefix string `json:"ip_prefix"` + Region string `json:"region"` + Services []string `json:"services"` + NetworkBorderGroup string `json:"network_border_group"` + } +} + +// Json implements checkip.Info +func (a awsIpRanges) Json() ([]byte, error) { + return json.Marshal(&a) +} + +// Summary implements checkip.Info +func (a awsIpRanges) Summary() string { + if a.IsOn { + return fmt.Sprintf("%t, prefix: %s, region: %s, sevices: %v", + a.IsOn, a.Info.IpPrefix, a.Info.Region, a.Info.Services) + } + return fmt.Sprintf("%t", a.IsOn) +} + +// IsOnAWS checks if ipaddr belongs to AWS. If so it provides info about the IP +// address. It gets the info from https://ip-ranges.amazonaws.com/ip-ranges.json +func IsOnAWS(ipaddr net.IP) (checkip.Result, error) { + result := checkip.Result{ + Name: "is on AWS", + } + resp := struct { + Prefixes []struct { + IpPrefix string `json:"ip_prefix"` + Region string `json:"region"` + Service string `json:"service"` + NetworkBorderGroup string `json:"network_border_group"` + } `json:"prefixes"` + }{} + apiUrl := "https://ip-ranges.amazonaws.com/ip-ranges.json" + if err := defaultHttpClient.GetJson(apiUrl, map[string]string{}, map[string]string{}, &resp); err != nil { + return result, newCheckError(err) + } + var a awsIpRanges + for _, prefix := range resp.Prefixes { + _, network, err := net.ParseCIDR(prefix.IpPrefix) + if err != nil { + return result, fmt.Errorf("parse CIDR %q: %v", prefix.IpPrefix, err) + } + if network.Contains(ipaddr) { + a.IsOn = true + a.Info.IpPrefix = prefix.IpPrefix + a.Info.NetworkBorderGroup = prefix.NetworkBorderGroup + a.Info.Region = prefix.Region + a.Info.Services = append(a.Info.Services, prefix.Service) + } + + } + result.Info = a + return result, nil +} diff --git a/check/isonaws_test.go b/check/isonaws_test.go new file mode 100644 index 0000000..52223ba --- /dev/null +++ b/check/isonaws_test.go @@ -0,0 +1,35 @@ +package check_test + +import ( + "net" + "testing" + + "github.com/jreisinger/checkip/check" +) + +func TestIsOnAWS(t *testing.T) { + tests := []struct { + ipAddr string + summary string + }{ + { + ipAddr: "54.74.0.27", + summary: "true, prefix: 54.74.0.0/15, region: eu-west-1, sevices: [AMAZON EC2]", + }, + { + ipAddr: "1.1.1.1", + summary: "false", + }, + } + + for i, test := range tests { + ipaddr := net.ParseIP(test.ipAddr) + r, err := check.IsOnAWS(ipaddr) + if err != nil { + t.Fatalf("check.IsOnAWS(%s) failed: %v", ipaddr, err) + } + if r.Info.Summary() != test.summary { + t.Errorf("test %d\ngot\t%q\nwant\t%q", i, r.Info.Summary(), test.summary) + } + } +}