Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

crowdsec unrecognized directive in Caddyfile #45

Open
boecks opened this issue Jul 2, 2024 · 1 comment
Open

crowdsec unrecognized directive in Caddyfile #45

boecks opened this issue Jul 2, 2024 · 1 comment

Comments

@boecks
Copy link

boecks commented Jul 2, 2024

I have Caddy running in Docker and originally installed the crowdsec plugin using

RUN xcaddy build \
    --with github.com/hslatman/caddy-crowdsec-bouncer/crowdsec

(note that this is the snippet provided at the caddy documentation for modules - and also it should have sufficed my use case since I only use reverse_proxy handlers, no L4)

Then I added the Crowdsec Config in the global block of my Caddyfile as given in your and crowdsec's guides. The communication between LAPI on my Firewall and the caddy-crowdsec-bouncer worked and I could verify that I got decisions from the LAPI to the bouncer. However, in order to make Caddy execute the decisions i.e. by blocking a banned IP, it is necessary to add the crowdsec directive inside a route block for a specific site configuration.
At this point, when adding the crowdsec directive inside a route block, Caddy would not start, but give me an error that crowdsec is an unrecognized directive.

After one day of troubleshooting, I decided to rebuild Caddy with the following snippet:

RUN xcaddy build \
    --with github.com/mholt/caddy-l4 \
    --with github.com/caddyserver/transform-encoder \
    --with github.com/hslatman/caddy-crowdsec-bouncer/http@main \
    --with github.com/hslatman/caddy-crowdsec-bouncer/layer4@main \
    --with github.com/hslatman/caddy-crowdsec-bouncer/crowdsec

Long story short, after that, crowdsec was recognized as directive and I could verify, banned IPs were blocked by crowdsec before reverse proxying.

I wanted to ask, what is the reason it did not work with the first snippet, but with the second.
Furthermore I want to suggest to provide this information somehow to assist anyone else experiencing this issues.
Maybe your or Crowdsec's guides could be extended or adapted to include some further information about this specific behaviour.

Thank you for your nice work on the caddy bouncer!

All the best!

Btw. my working Dockerfile and Caddyfile:

#Docekrfile
FROM caddy:builder AS builder

RUN xcaddy build \
    --with github.com/caddy-dns/cloudflare \
    --with github.com/mholt/caddy-l4 \
    --with github.com/caddyserver/transform-encoder \
    --with github.com/hslatman/caddy-crowdsec-bouncer/http@main \
    --with github.com/hslatman/caddy-crowdsec-bouncer/layer4@main \
    --with github.com/hslatman/caddy-crowdsec-bouncer/crowdsec

FROM caddy:latest

COPY --from=builder /usr/bin/caddy /usr/bin/caddy
#Caddyfile
{
	acme_dns cloudflare XXXXXXXXXXXXXXXXXXXXXXXXXXX

	crowdsec {
		api_key XXXXXXXXXXXXXXXXXXXXXXXXXXX
		api_url http://LAPI:port/
		ticker_interval 10s
	}
}

test.example.com {
	log {
		level INFO
		format console
		output file /var/log/caddy/test1-access.log {
			roll_size 10MB
			roll_keep 10
		}
	}

	encode gzip

	header /* {
		Strict-Transport-Security "max-age=31536000;"
		X-XSS-Protection "1; mode=block"
		X-Robots-Tag "none"
		X-Content-Type-Options "nosniff"
		X-Content-Security-Policy "default-src 'self'"
		Permissions-Policy "microphone=(), geolocation=()"
	}

	route {
		crowdsec
		reverse_proxy targethost:port {
			header_up X-Real-IP {remote_host}
		}
	}
}

Regarding the docker-compose.yaml the guide at https://github.com/crowdsecurity/example-docker-compose/tree/main/caddy works well. I just used environment variables to configure crowdsec on this machine as log processor only. Found the information about the variables at https://hub.docker.com/r/crowdsecurity/crowdsec

@hslatman
Copy link
Owner

hslatman commented Jul 2, 2024

Hi @AlpenFlizzer,

The automatically generated Caddy documentation shows the docs for github.com/hslatman/caddy-crowdsec-bouncer/crowdsec because that's a Caddy module for a Caddy app. However, that itself does not include the http.Handler Caddy module that's in github.com/hslatman/caddy-crowdsec-bouncer/http (which also exists in the autogenerated Caddy documentation: https://caddyserver.com/docs/modules/http.handlers.crowdsec). The app module provides shared configuration, logic and storage for multiple HTTP handlers. And it does the same for the layer4 module, which you only need if you want it to work on the TCP/UDP level too.

The usage of two modules in the custom build is shown and explained in https://github.com/hslatman/caddy-crowdsec-bouncer?tab=readme-ov-file#usage. In fact, importing just github.com/hslatman/caddy-crowdsec-bouncer/http is sufficient, as it depends on github.com/hslatman/caddy-crowdsec-bouncer/crowdsec for shared functionality, so it will automatically import the app module too. That is also what happens in https://github.com/crowdsecurity/example-docker-compose/blob/main/caddy/Dockerfile.

You're not the first one to hit this case; this one was relatively recent: #44. I'll see if I can improve the docs by 1) showing a full xcaddy example, and 2) mentioning somewhere in the app module docs that the http.handlers.crowdsec module is needed to for this to do some actual work, so that it will show up on the Caddy docs. It might also be possible to log a warning or an error at startup when crowdsec is loaded successfully, but http.handlers.crowdsec is not, so that at least it's clear that the configuration is not fully functional yet. I'm not sure if the crowdsec is an unrecognized directive error message can be improved. It would be nice to indicate to a user then need the http.handlers.crowdsec module in that case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants