-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcheck_abuseipdb.go
174 lines (146 loc) · 5.2 KB
/
check_abuseipdb.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
package main
import (
"bytes"
"encoding/json"
"errors"
"flag"
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
var version string
var compileDate string
const (
ExitCodeOk = iota
ExitCodeWarning
ExitCodeCritical
ExitCodeUnknown
)
var AbuseIpDbCategories = map[int]string{
3: "Fraud Orders", 4: "DDoS Attack",
5: "FTP Brute-Force", 6: "Ping of Death",
7: "Phishing", 8: "Fraud VoIP",
9: "Open Proxy", 10: "Web Spam",
11: "Email Spam", 12: "Blog Spam",
13: "VPN IP", 14: "Port Scan",
15: "Hacking", 16: "SQL Injection",
17: "Spoofing", 18: "Brute-Force",
19: "Bad Web Bot", 20: "Exploited Host",
21: "Web App Attack", 22: "SSH", 23: "IoT Targeted",
}
type AbuseIpDbCheckResponse struct {
Data AbuseIpDbCheckData `json:"data"`
}
type AbuseIpDbCheckData struct {
IpAddress string `json:"ipAddress"`
IsPublic bool `json:"isPublic"`
IpVersion int `json:"ipVersion"`
IsWhitelisted bool `json:"isWhitelisted"`
AbuseConfidenceScore int `json:"abuseConfidenceScore"`
CountryCode string `json:"countryCode"`
UsageType string `json:"usageType"`
Isp string `json:"isp"`
Domain string `json:"domain"`
TotalReports int `json:"totalReports"`
NumDistinctUsers int `json:"numDistinctUsers"`
LastReportedAt string `json:"lastReportedAt"`
Reports []AbuseIpDbCheckReport `json:"reports"`
}
type AbuseIpDbCheckReport struct {
ReportedAt string `json:"reportedAt"`
Comment string `json:"comment"`
Categories []int `json:"categories"`
ReporterId int `json:"reporterId"`
ReporterCountryCode string `json:"reporterCountryCode"`
ReporterCountryName string `json:"reporterCountryName"`
}
func buildStatusMessage(checkData AbuseIpDbCheckData) string {
var reasonStr string
if len(checkData.Reports) > 0 {
var reasons = make(map[int]string) // Slice of *unique* reason strings
for _, report := range checkData.Reports {
for _, categoryId := range report.Categories {
reasons[categoryId] = AbuseIpDbCategories[categoryId]
}
}
for _, reason := range reasons {
reasonStr += reason + ", "
}
}
return strings.TrimRight(fmt.Sprintf("Found %d entries for %s from %d users (Abuse Probability: %d%%) %s",
checkData.TotalReports, checkData.IpAddress, checkData.NumDistinctUsers, checkData.AbuseConfidenceScore, reasonStr), ", ")
}
func main() {
address := flag.String("host", "", "Host to check")
apiKey := flag.String("key", "", "abuseipdb APIv2 key")
daysToCheck := flag.Int("days", 14, "Timespan to check in days")
warnCount := flag.Int("warn", 1, "Minimum reports to return a WARN")
critCount := flag.Int("crit", 3, "Minimum reports to return a CRIT")
versionPrint := flag.Bool("version", false, "Prints the version and exits")
flag.Parse()
if *versionPrint {
fmt.Printf("abuseipdb-check - version %s (compiled at %s)\nCopyright (c) 2024 webförsterei Softwareentwicklung GmbH & Co. KG (MIT-License applies)\ngithub.com/webfoersterei/abuseipdb-check\n", version, compileDate)
os.Exit(ExitCodeOk)
}
if len(strings.Trim(*address, " ")) == 0 {
fmt.Print("Invalid arguments: No address provided via -host")
os.Exit(ExitCodeUnknown)
}
if len(strings.Trim(*apiKey, " ")) == 0 {
fmt.Print("Invalid arguments: No API-Key provided via -key")
os.Exit(ExitCodeUnknown)
}
if *warnCount > *critCount {
fmt.Printf("Invalid arguments: WarnCount (%d) greater then CritCount (%d)\n", *warnCount, *critCount)
os.Exit(ExitCodeUnknown)
}
apiResult, err := getEntryCount(apiKey, address, daysToCheck)
if err != nil {
fmt.Println("UNKNOWN - Error: ", err)
os.Exit(ExitCodeUnknown)
}
statusMessage := buildStatusMessage(apiResult)
if apiResult.TotalReports >= *critCount {
fmt.Printf("CRITICAL - %s", statusMessage)
os.Exit(ExitCodeCritical)
} else if apiResult.TotalReports >= *warnCount {
fmt.Printf("WARNING - %s", statusMessage)
os.Exit(ExitCodeWarning)
}
fmt.Printf("OK - %s", statusMessage)
os.Exit(ExitCodeOk)
}
func getEntryCount(apiKey *string, address *string, daysToCheck *int) (AbuseIpDbCheckData, error) {
url := fmt.Sprintf("https://api.abuseipdb.com/api/v2/check?ipAddress=%s&maxAgeInDays=%d&verbose=1", *address, *daysToCheck)
client := &http.Client{
Timeout: time.Second * 30,
}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return AbuseIpDbCheckData{}, err
}
req.Header.Add("User-Agent", fmt.Sprintf("check_abuseipdb/%s (golang/http; Github: webfoersterei)", version))
req.Header.Add("Accept", "application/json")
req.Header.Add("Key", *apiKey)
resp, err := client.Do(req)
if err != nil {
return AbuseIpDbCheckData{}, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return AbuseIpDbCheckData{}, err
}
if resp.StatusCode != 200 {
return AbuseIpDbCheckData{}, errors.New(string(bytes.TrimSpace(body)))
}
response := AbuseIpDbCheckResponse{}
err = json.Unmarshal(body, &response)
if err != nil {
return AbuseIpDbCheckData{}, err
}
return response.Data, err
}