Skip to content

Examples

This part of the documentation contains usable examples which you can refer to when writing your caddyfile(s).

Responder Types

Caddy Defender supports multiple response strategies:

Responder Description Configuration Required
block Immediately blocks requests with 403 Forbidden No
custom Returns a custom text response message field required
drop Drops the connection No
garbage Returns random garbage data to confuse scrapers/AI No
ratelimit Marks requests for rate limiting (requires caddy-ratelimit integration) Additional rate limit config
redirect Returns 308 Permanent Redirect response url field required
tarpit Stream data at a slow, but configurable rate to stall bots and pollute AI training. tarpit_config block required

Block Requests

Block requests from specific IP ranges with 403 Forbidden:

Example 1

localhost:8080 {
    defender block {
        ranges 203.0.113.0/24 openai 198.51.100.0/24
    }
    respond "Human-friendly content"
}

# JSON equivalent
{
    "handler": "defender",
    "raw_responder": "block",
    "ranges": ["203.0.113.0/24", "openai"]
}

Example 2

{
    auto_https off
    order defender after header
    debug
}

:80 {
    bind 127.0.0.1 ::1

    defender block {
        ranges private
    }
    respond "This is what a human sees"
}

:83 {
    bind 127.0.0.1 ::1
    respond "Clear text HTTP"
}

Custom Response

Return tailored messages for blocked requests:

Example 1

localhost:8080 {
    defender custom {
        ranges 10.0.0.0/8
        message "Access restricted for your network"
    }
    respond "Public content"
}

# JSON equivalent
{
    "handler": "defender",
    "raw_responder": "custom",
    "ranges": ["10.0.0.0/8"],
    "message": "Access restricted for your network"
}

Example 2

{
    auto_https off
    order defender after header
    debug
}

:80 {
    bind 127.0.0.1 ::1

    defender custom {
        ranges private
        message "You are not welcome here"
    }
    respond "This is what a human sees"
}

:83 {
    bind 127.0.0.1 ::1

    respond "Clear text HTTP"
}

Drop connections

Drop connections rather than send a response:

Example 1

localhost:8080 {
    defender drop {
        ranges 203.0.113.0/24 openai 198.51.100.0/24
    }
}

# JSON equivalent
{
    "handler": "defender",
    "raw_responder": "drop",
    "ranges": ["203.0.113.0/24", "openai"]
}

Example 2

{
    auto_https off
    order defender after header
    debug
}

:80 {
    bind 127.0.0.1 ::1

    defender drop {
        ranges private
    }
}

Return Garbage Data

Return meaningless content for AI/scrapers:

Example 1

localhost:8080 {
    defender garbage {
        ranges 192.168.0.0/24
    }
    respond "Legitimate content"
}

# JSON equivalent
{
    "handler": "defender",
    "raw_responder": "garbage",
    "ranges": ["192.168.0.0/24"]
}

Example 2

{
    auto_https off
    order defender after header
    debug
}

:80 {
    bind 127.0.0.1 ::1

    defender garbage {
        ranges private
        serve_ignore
    }
    respond "This is what a human sees"
}

:83 {
    bind 127.0.0.1 ::1

    respond "Clear text HTTP"
}

Rate Limiting

Integrate with caddy-ratelimit:

{
    order rate_limit after basic_auth
}

:80 {
    defender ratelimit {
        ranges private
    }

    rate_limit {
        zone static_example {
            match {
                method GET
                header X-RateLimit-Apply true
            }
            key {remote_host}
            events 3
            window 1m
        }
    }

    respond "Hey I'm behind a rate limit!"
}

For complete rate limiting documentation, see Rate Limiting Configuration and caddy-ratelimit.


Redirect Response

Redirect requests:

Example 1

localhost:8080 {
    defender redirect {
        ranges 10.0.0.0/8
        url "https://example.com"
    }
}

# JSON equivalent
{
    "handler": "defender",
    "raw_responder": "redirect",
    "ranges": ["10.0.0.0/8"],
    "url": "https://example.com"
}

Example 2

{
    auto_https off
    order defender after header
    debug
}

:80 {
    bind 127.0.0.1 ::1

    defender redirect {
        ranges private
        url "https://example.com"
    }
}

Tarpit

Stream data at a slow, but configurable rate to stall bots and pollute AI training.

Example 1

localhost:8080 {
    defender tarpit {
        ranges private
        tarpit_config {
            # Optional headers
            headers {
                X-You-Got Played
            }
            # Optional. Use content from local file to stream slowly. Can also use source from http/https which is cached locally.
            content file://some-file.txt
            # Optional. Complete request at this duration if content EOF is not reached. Default 30s
            timeout 30s
            # Optional. Rate of data stream. Default 24
            bytes_per_second 24
            # Optional. HTTP Response Code Default 200
            response_code 200
        }
    }
}

# JSON equivalent
{
    "handler": "defender",
    "raw_responder": "tarpit",
    "ranges": ["10.0.0.0/8"],
    "tarpit_config": {
        "headers": {
             "X-You-Got" "Played"
        },
        "content": "file://some-file.txt",
        "timeout": "30s",
        "bytes_per_second": 24,
        "response_code": 200
    }
}

Example 2

{
    auto_https off
    order defender after header
    debug
}

:80 {
    bind 127.0.0.1 ::1

    defender tarpit {
        ranges private
        tarpit_config {
            # Optional headers
            headers {
                X-You-Got "Played"
            }
            # Optional. Use content from local file to stream slowly. Can also use source from http/https which is cached locally.
            # content file://some-file.txt
            content https://www.cloudflare.com/robots.txt
            # Optional. Complete request at this duration if content EOF is not reached. Default 30s
            timeout 30s
            # Optional. Rate of data stream. Default 24
            bytes_per_second 24
            # Optional. HTTP Response Code Default 200
            response_code 200
        }
    }
}

Combination Example

Mix multiple response strategies:

example.com {
    defender block {
        ranges known-bad-actors
    }

    defender ratelimit {
        ranges aws
    }

    defender garbage {
        ranges scrapers
    }

    respond "Main Website Content"
}

Whitelisting

Whitelist certain IP(s) from blocked ranges:

{
    auto_https off
    order defender after header
    debug
}

:80 {
    bind 127.0.0.1 ::1
    # Everything in AWS besides my EC2 instance is blocked from accessing this site.
    defender block {
        ranges aws
        whitelist 169.254.169.254 # my ec2's public IP.
    }
    respond "This is what a human sees"
}

:81 {
    bind 127.0.0.1 ::1
    # My localhost ipv6 is blocked but not my ipv4
    defender block {
        ranges private
        whitelist 127.0.0.1
    }
    respond "This is what a ipv4 human sees"
}

geoip

See issue #27.

From caddy-maxmind-geolocation:

localhost:8080 {
  @mygeofilter {
    maxmind_geolocation {
      db_path "/usr/share/GeoIP/GeoLite2-Country.mmdb"
      allow_countries IT FR # Allow access to the website only from Italy and France
    }
  }

   file_server @mygeofilter {
     root /var/www/html
   }
}