Plugin idea: Bad IP checker

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. :slight_smile:

Based on the CURL info from AbuseIPDB indfo below.

Go code:

package main

import (

// Response struct to unmarshal JSON response
type Response struct {
    TotalReports bool `json:"totalReports"`

func main() {
    apiUrl := ""
    ipAddress := ""
    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 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 \
  --data-urlencode "ipAddress=" \
  -d maxAgeInDays=90 \
  -d verbose \
  -H "Key: YOUR_OWN_API_KEY" \
  -H "Accept: application/json"

This will yield the following JSON response:

    "data": {
      "ipAddress": "",
      "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": "",
      "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",
          "categories": [
          "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.