Caddy, Cloudflare proxy and Client IP Headers

Started by Lemimouth, March 24, 2025, 07:32:17 PM

Previous topic - Next topic
Why would you prefer to bounce in Caddy instead of just blocking the IP address in pf on WAN? I am not arguing against acquiring via Caddy and Caddy logs - I specifically implemented the "plain text access log" feature for that. But once you register a malicious host, I'd block it at the frontmost point of my network available before it even reaches and application. That's firewall on WAN.
Deciso DEC750
People who think they know everything are a great annoyance to those of us who do. (Isaac Asimov)

January 09, 2026, 03:57:24 PM #16 Last Edit: January 09, 2026, 03:59:56 PM by Monviech (Cedrik)
I guess crowdsec only parses the source IP of the request and if Cloudflare is the proxy, that would always be cloudflare's IP address.

The bouncer can probably use the header "CF-Connecting-IP" https://developers.cloudflare.com/fundamentals/reference/http-headers/

Though maybe the crowdsec parser could be made more intelligent? I dont know.

Though in the caddy plugin you can already alter client_ip https://caddyserver.com/docs/json/apps/http/servers/client_ip_headers/

This is also implemented, so client_ip could be set to CF-Connecting-IP, so I assume crowdsec would parse correctly?
Hardware:
DEC740

Ah ... so blocking based on X-Forwarded-For: or similar as received from Cloudflare - get it.
Deciso DEC750
People who think they know everything are a great annoyance to those of us who do. (Isaac Asimov)

Since the scope of the caddy plugin is rather tight now (only cloudflare), a cloudflare bouncer could be theoretically compiled in and made a part of it. Yet I don't want to do it, and each new part makes maintainance harder.

Right now it's so peacefully quiet :)
Hardware:
DEC740

I think i managed to do something...

first, backup the standard binary
cp /usr/local/bin/caddy /usr/local/bin/caddy.backup


download the new built binary with all the needed modules:

fetch -o /tmp/caddy-custom "https://caddyserver.com/api/download?os=freebsd&arch=amd64&p=github.com%2Fcaddy-dns%2Fcloudflare&p=github.com%2Fmholt%2Fcaddy-l4&p=github.com%2Fmholt%2Fcaddy-dynamicdns&p=github.com%2Fmholt%2Fcaddy-ratelimit&p=github.com%2Fcaddyserver%2Fntlm-transport&p=github.com%2Fhslatman%2Fcaddy-crowdsec-bouncer&idempotency=26094258780053"

fix permissions and move

chmod +x /tmp/caddy-custom
mv /tmp/caddy-custom /usr/local/bin/caddy


Now create a bouncer:
cscli bouncers add caddy-bouncer

save the API Key


then I created a .global file in /usr/local/etc/caddy/caddy.d

order crowdsec before reverse_proxy

crowdsec {
    api_url http://opnsense LAPI
    api_key key of the created bouncer
    ticker_interval 15s
}


then i had to add crowdsec in the handler.
unluckly it is not doable from the GUI, so I had to deactivate all my domain in the guy, create a .conf file in /usr/local/etc/caddy/caddy.d

my.domain.com {
        log {
                output file /var/log/caddy/access/b49df191-a08d-4f12-9834-bb15ceb8b3d0.log {
                        roll_keep_for 10d
                }
        }
        tls {
                issuer acme {
                        dns cloudflare API KEY CLOUDFLARE
                }
        }

        handle {
                crowdsec
                reverse_proxy ip:port {
                }
        }
}


it seems to work!


surely can be done in a more elegant way...