Skip to content

Commit

Permalink
Add AbuseIPDB
Browse files Browse the repository at this point in the history
  • Loading branch information
evalphobia committed Oct 28, 2021
1 parent 33daee1 commit f6a5c3c
Show file tree
Hide file tree
Showing 8 changed files with 176 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ it provides both of cli binary and golang API.

# Supported Providers

- [AbuseIPDB](https://www.abuseipdb.com/)
- [Big Data Cloud](https://www.bigdatacloud.com/)
- [IP2Proxy](https://www.ip2location.com/web-service/ip2proxy)
- [ipdata.co](https://ipdata.co/)
Expand Down Expand Up @@ -246,6 +247,7 @@ see example dir for more examples.
| Name | Description |
|:--|:--|
| `FRAUD_CHECK_ABUSEIPDB_APIKEY` | [AbuseIPDB API Key](https://docs.abuseipdb.com/). |
| `BIGDATACLOUD_APIKEY` | [Big Data Cloud API Key](https://www.bigdatacloud.com/sdk). |
| `FRAUD_CHECK_IP2PROXY_APIKEY` | [ip2proxy API key](https://www.ip2location.com/web-service/ip2proxy/). |
| `FRAUD_CHECK_IP2PROXY_PACKAGE` | [ip2proxy package parameter](https://www.ip2location.com/web-service/ip2proxy/). |
Expand Down
3 changes: 3 additions & 0 deletions cmd/providers.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"strings"

"github.com/evalphobia/go-ip-fraud-check/provider"
"github.com/evalphobia/go-ip-fraud-check/provider/abuseipdb"
"github.com/evalphobia/go-ip-fraud-check/provider/bigdatacloud"
"github.com/evalphobia/go-ip-fraud-check/provider/ip2proxy"
"github.com/evalphobia/go-ip-fraud-check/provider/ipdataco"
Expand All @@ -17,6 +18,7 @@ import (
)

const (
providerAbuseIPDB = "abuseipdb"
providerBigDataCloud = "bigdatacloud"
providerIP2Proxy = "ip2proxy"
providerIPdataco = "ipdata"
Expand All @@ -29,6 +31,7 @@ const (
)

var providerMap = map[string]provider.Provider{
providerAbuseIPDB: &abuseipdb.AbuseIPDBProvider{},
providerBigDataCloud: &bigdatacloud.BigDataCloudProvider{},
providerIP2Proxy: &ip2proxy.IP2ProxyProvider{},
providerIPdataco: &ipdataco.IPdatacoProvider{},
Expand Down
11 changes: 11 additions & 0 deletions ipfraudcheck/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
)

const (
envAbuseIPDBAPIKey = "FRAUD_CHECK_ABUSEIPDB_APIKEY"
envIP2ProxyAPIKey = "FRAUD_CHECK_IP2PROXY_APIKEY"
envIP2ProxyAPIPackage = "FRAUD_CHECK_IP2PROXY_PACKAGE"
envIPdatacoAPIKey = "FRAUD_CHECK_IPDATACO_APIKEY"
Expand All @@ -24,6 +25,8 @@ const (

// Config contains parameters for IP check API providers.
type Config struct {
// abuseipdb.com
AbuseIPDBAPIKey string
// bigdatacloud.com
BigDataCloudAPIKey string
// ip2location.com
Expand Down Expand Up @@ -62,6 +65,14 @@ func (c Config) GetLogger() log.Logger {
return c.Logger
}

func (c Config) GetAbuseUPDBAPIKey() string {
s := os.Getenv(envAbuseIPDBAPIKey)
if s != "" {
return s
}
return c.AbuseIPDBAPIKey
}

func (c Config) GetIP2ProxyAPIKey() string {
s := os.Getenv(envIP2ProxyAPIKey)
if s != "" {
Expand Down
41 changes: 41 additions & 0 deletions provider/abuseipdb/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package abuseipdb

import (
"github.com/evalphobia/go-ip-fraud-check/provider/privateclient"
)

const (
defaultBaseURL = "https://api.abuseipdb.com"
)

type Client struct {
apiKey string
privateclient.RESTClient
}

func NewClient(apiKey string) Client {
return Client{
apiKey: apiKey,
RESTClient: privateclient.RESTClient{
Option: privateclient.Option{
Headers: map[string]string{"KEY": apiKey},
BaseURL: defaultBaseURL,
},
},
}
}

func (c *Client) SetDebug(b bool) {
c.RESTClient.Debug = b
}

func (c Client) Check(ipaddr string) (Response, error) {
params := make(map[string]string)
params["ipAddress"] = ipaddr
params["maxAgeInDays"] = "365"
params["verbose"] = ""

resp := Response{}
err := c.RESTClient.CallGET("/api/v2/check", params, &resp)
return resp, err
}
68 changes: 68 additions & 0 deletions provider/abuseipdb/provider_abuseipdb.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package abuseipdb

import (
"errors"
"fmt"
"strings"

"github.com/evalphobia/go-ip-fraud-check/ipfraudcheck"
"github.com/evalphobia/go-ip-fraud-check/provider"
)

type AbuseIPDBProvider struct {
client Client
}

func (p *AbuseIPDBProvider) Init(conf provider.Config) error {
c, ok := conf.(ipfraudcheck.Config)
if !ok {
return errors.New("incompatible config type for AbuseIPDBProvider")
}

apiKey := c.GetAbuseUPDBAPIKey()
if apiKey == "" {
return errors.New("apikey for AbuseIPDB is empty. you must set directly or use 'FRAUD_CHECK_ABUSEIPDB_APIKEY' envvar")
}
cli := NewClient(apiKey)
cli.SetDebug(c.Debug)
p.client = cli
return nil
}

func (p AbuseIPDBProvider) String() string {
return "AbuseIPDB"
}

func (p AbuseIPDBProvider) CheckIP(ipaddr string) (provider.FraudCheckResponse, error) {
emptyResult := provider.FraudCheckResponse{}

resp, err := p.client.Check(ipaddr)
if err != nil {
return emptyResult, err
}

d := resp.Data
var comments []string
if d.NumDistinctUsers != 0 {
comments = append(comments, fmt.Sprintf("distinct_users=[%d]", d.NumDistinctUsers))
}
if d.UsageType != "" {
comments = append(comments, d.UsageType)
}

return provider.FraudCheckResponse{
ServiceName: p.String(),
IP: ipaddr,
Hostname: d.Domain,
ISP: d.ISP,
Country: d.CountryCode,
HasOtherThreat: d.TotalReports > 0,
IsHosting: d.IsHosting(),
RiskScore: float64(d.AbuseConfidenceScore) / 100,
ThreatComment: strings.Join(comments, " | "),
}, nil
}

func (p AbuseIPDBProvider) RawCheckIP(ipaddr string) (interface{}, error) {
return p.client.Check(ipaddr)
}
41 changes: 41 additions & 0 deletions provider/abuseipdb/response.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package abuseipdb

type Response struct {
Data Data `json:"data"`
}

type Data struct {
IPAddress string `json:"ipAddress"`
IPVersion int64 `json:"ipVersion"`
ISP string `json:"isp"`
Domain string `json:"domain"`
Hostnames []string `json:"hostnames"`
CountryCode string `json:"countryCode"`
CountryName string `json:"countryName"`
IsPublic bool `json:"isPublic"`
IsWhitelisted bool `json:"isWhitelisted"`
AbuseConfidenceScore int64 `json:"abuseConfidenceScore"`
UsageType string `json:"usageType"`
TotalReports int64 `json:"totalReports"`
NumDistinctUsers int64 `json:"numDistinctUsers"`
LastReportedAt string `json:"lastReportedAt"`
Reports []Report `json:"reports"`
}

func (d Data) IsHosting() bool {
_, ok := hostingMap[d.UsageType]
return ok
}

type Report struct {
ReportedAt string `json:"reportedAt"`
Comment string `json:"comment"`
Categories []int64 `json:"categories"`
ReporterID int64 `json:"reporterId"`
ReporterCountryCode string `json:"reporterCountryCode"`
ReporterCountryName string `json:"reporterCountryName"`
}

var hostingMap = map[string]struct{}{
"Data Center/Web Hosting/Transit": struct{}{},
}
8 changes: 8 additions & 0 deletions provider/privateclient/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ var defaultUserAgent = fmt.Sprintf("go-ip-fraud-check/%s", clientVersion)
// Option contains optional setting of RESTClient.
type Option struct {
BaseURL string
Headers map[string]string
UserAgent string
Timeout time.Duration
Debug bool
Expand Down Expand Up @@ -42,3 +43,10 @@ func (o Option) getTimeout() time.Duration {
}
return defaultTimeout
}

func (o Option) getHeaders() map[string]string {
if len(o.Headers) != 0 {
return o.Headers
}
return nil
}
2 changes: 2 additions & 0 deletions provider/privateclient/restclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func (c *RESTClient) CallGET(path string, params, result interface{}) (err error
Pass: c.BasicAuthPass,
Retry: opt.Retry,
Debug: opt.Debug,
Headers: opt.getHeaders(),
UserAgent: opt.getUserAgent(),
Timeout: opt.getTimeout(),
})
Expand All @@ -61,6 +62,7 @@ func (c *RESTClient) CallPOST(path string, params, result interface{}) (err erro
Pass: c.BasicAuthPass,
Retry: opt.Retry,
Debug: opt.Debug,
Headers: opt.getHeaders(),
UserAgent: opt.getUserAgent(),
Timeout: opt.getTimeout(),
})
Expand Down

0 comments on commit f6a5c3c

Please sign in to comment.