I’d love to have a plugin that checks request IPs against AbuseIPDB and the like and block them if considered bots or otherwise potentially malicious.
Take a shot at writing it yourself. Caddy plugins are very easy to write, even for Go beginners:
Even did Caddy plugin development before (caddy-remote-host) and might actually give this a shot at some point. Still wanted to drop the idea here, just in case someone is eager to jump right onto it.
As a starter for 10. The Go would be fairly close to the following.
Based on the CURL info from AbuseIPDB indfo below.
Go code:
package main
import (
"fmt"
"net/http"
"net/url"
)
// Response struct to unmarshal JSON response
type Response struct {
TotalReports bool `json:"totalReports"`
}
func main() {
apiUrl := "https://api.abuseipdb.com/api/v2/check"
ipAddress := "118.25.6.39"
maxAgeInDays := "90"
apiKey := "RANDOMAPIKEY"
result := checkIP(ipAddress,maxAgeInDays )
fmt.Println("Result:", result)
}
Returns false if there is an error or is not in the AbuseIPDB
else returns 127.0.0.1 if is in the abuse DB
func checkIP( apiKey string , ipAddress string, maxAgeInDays integer) bool{
// Create HTTP client
client := &http.Client{}
// Prepare request
req, err := http.NewRequest("GET", apiUrl, nil)
if err != nil {
fmt.Println("Error creating request:", err)
return false
}
// Add query parameters
queryParams := req.URL.Query()
queryParams.Add("ipAddress", ipAddress)
queryParams.Add("maxAgeInDays", maxAgeInDays)
queryParams.Add("verbose", "")
req.URL.RawQuery = queryParams.Encode()
// Add headers
req.Header.Set("Key", apiKey)
req.Header.Set("Accept", "application/json")
// Send request
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error sending request:", err)
return false
}
defer resp.Body.Close()
// Handle response
// You can read the response body here and parse it as needed
// For example, you can use json.Decoder to decode JSON response
// resp.Body contains the response body
fmt.Println("Response Status:", resp.Status)
// Decode JSON response
var response Response
if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
fmt.Println("Error decoding JSON:", err)
return false// Return original IP address on error
}
// Check if badblock is true
if response.BadBlock {
return true
}
return false
}
From AbuseIPDB info on using the API:
# The -G option will convert form parameters (-d options) into query parameters.
# The CHECK endpoint is a GET request.
curl -G https://api.abuseipdb.com/api/v2/check \
--data-urlencode "ipAddress=118.25.6.39" \
-d maxAgeInDays=90 \
-d verbose \
-H "Key: YOUR_OWN_API_KEY" \
-H "Accept: application/json"
This will yield the following JSON response:
{
"data": {
"ipAddress": "118.25.6.39",
"isPublic": true,
"ipVersion": 4,
"isWhitelisted": false,
"abuseConfidenceScore": 100,
"countryCode": "CN",
"countryName": "China",
"usageType": "Data Center/Web Hosting/Transit",
"isp": "Tencent Cloud Computing (Beijing) Co. Ltd",
"domain": "tencent.com",
"hostnames": [],
"isTor": false,
"totalReports": 1,
"numDistinctUsers": 1,
"lastReportedAt": "2018-12-20T20:55:14+00:00",
"reports": [
{
"reportedAt": "2018-12-20T20:55:14+00:00",
"comment": "Dec 20 20:55:14 srv206 sshd[13937]: Invalid user oracle from 118.25.6.39",
"categories": [
18,
22
],
"reporterId": 1,
"reporterCountryCode": "US",
"reporterCountryName": "United States"
}
]
}
}
Implementing this would be trivial. I’m only worried about the added latency. Every first incoming request would be blocked by a round trip to the AbusdeIPDB API.
This topic was automatically closed after 30 days. New replies are no longer allowed.