C
CrowdSec6mo ago
ook

k8s Traefik bouncer: decision not applied

Hi, On a running k8s v1.28 + Traefik 3.3 existing cluster, I’m trying to integrate Crowdsec and its Traefik bouncer as traefik plugin. I see traefik log acquisition is correctly done on the agent:
crowdsec-agent-4wklc:/var/log# cscli metrics show acquisition
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Acquisition Metrics │
├──────────────────────────────┬────────────┬──────────────┬────────────────┬────────────────────────┬───────────────────┤
│ Source │ Lines read │ Lines parsed │ Lines unparsed │ Lines poured to bucket │ Lines whitelisted │
├──────────────────────────────┼────────────┼──────────────┼────────────────┼────────────────────────┼───────────────────┤
│ file:/traefik-log/access.log │ 18 │ 18 │ - │ 12 │ - │
╰──────────────────────────────┴────────────┴──────────────┴────────────────┴────────────────────────┴───────────────────╯
crowdsec-agent-4wklc:/var/log# cscli metrics show acquisition
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Acquisition Metrics │
├──────────────────────────────┬────────────┬──────────────┬────────────────┬────────────────────────┬───────────────────┤
│ Source │ Lines read │ Lines parsed │ Lines unparsed │ Lines poured to bucket │ Lines whitelisted │
├──────────────────────────────┼────────────┼──────────────┼────────────────┼────────────────────────┼───────────────────┤
│ file:/traefik-log/access.log │ 18 │ 18 │ - │ 12 │ - │
╰──────────────────────────────┴────────────┴──────────────┴────────────────┴────────────────────────┴───────────────────╯
But when I add manualy a ban decision, it’s like the middleware doesn’t check the decisions and let the request pass. What can I do wrong? Here my traefik relevant configuration part:
- --experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
- --experimental.plugins.bouncer.version=v1.4.1
- --experimental.plugins.bouncer.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
- --experimental.plugins.bouncer.version=v1.4.1
The traefik logs show the plugin correctly loaded:
33 Replies
CrowdSec
CrowdSec6mo ago
Important Information
This post has been marked as resolved. If this is a mistake please press the red button below or type /unresolve
© Created By WhyAydan for CrowdSec ❤️
ook
ookOP6mo ago
2025-03-24T22:54:16Z INF Loading plugins... plugins=["bouncer","cloudflarewarp"]
2025-03-24T22:54:26Z ERR Request failed error={"Err":{},"Op":"Get","URL":"https://plugins.traefik.io/public/download/github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/v1.4.1"} metho
d=GET url=https://plugins.traefik.io/public/download/github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/v1.4.1
2025-03-24T22:54:27Z INF Plugins loaded. plugins=["bouncer","cloudflarewarp"]
2025-03-24T22:54:16Z INF Loading plugins... plugins=["bouncer","cloudflarewarp"]
2025-03-24T22:54:26Z ERR Request failed error={"Err":{},"Op":"Get","URL":"https://plugins.traefik.io/public/download/github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/v1.4.1"} metho
d=GET url=https://plugins.traefik.io/public/download/github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/v1.4.1
2025-03-24T22:54:27Z INF Plugins loaded. plugins=["bouncer","cloudflarewarp"]
Any help welcome, thanks by advance 🙂 Here the middleware configuration:
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: bouncer
namespace: default
spec:
plugin:
bouncer:
enabled: true
logLevel: DEBUG
crowdsecMode: stream
crowdsecLapiScheme: http
crowdsecLapiHost: crowdsec-service.crowdsec:8080
crowdsecLapiKey: REDACTEDSHAREDKEY
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: bouncer
namespace: default
spec:
plugin:
bouncer:
enabled: true
logLevel: DEBUG
crowdsecMode: stream
crowdsecLapiScheme: http
crowdsecLapiHost: crowdsec-service.crowdsec:8080
crowdsecLapiKey: REDACTEDSHAREDKEY
Here the ingressroute using the middleware:
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
creationTimestamp: "2025-03-19T09:49:26Z"
generation: 4
name: redacted
namespace: default
resourceVersion: "1187683790"
uid: c0bcf690-72c0-4453-89c0-c00d9f80c438
spec:
entryPoints:
- websecure
routes:
- kind: Rule
middlewares:
- name: bouncer
namespace: default
match: Host(`redacted.domain.tls`) && PathPrefix(`/`)
services:
- kind: Service
name: redactedservicename
port: 80
syntax: v2
tls:
certResolver: leweb
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
creationTimestamp: "2025-03-19T09:49:26Z"
generation: 4
name: redacted
namespace: default
resourceVersion: "1187683790"
uid: c0bcf690-72c0-4453-89c0-c00d9f80c438
spec:
entryPoints:
- websecure
routes:
- kind: Rule
middlewares:
- name: bouncer
namespace: default
match: Host(`redacted.domain.tls`) && PathPrefix(`/`)
services:
- kind: Service
name: redactedservicename
port: 80
syntax: v2
tls:
certResolver: leweb
blotus
blotus6mo ago
What is the output of cscli bouncers list in the LAPI pod ?
ook
ookOP6mo ago
Hi blotus, thank you for your assistance:
crowdsec-lapi-58cbf76bff-j8jgm:/# cscli bouncer list
─────────────────────────────────────────────────────────────────────────────
Name IP Address Valid Last API pull Type Version Auth Type
─────────────────────────────────────────────────────────────────────────────
crowdsecBouncer ✔️ api-key
TRAEFIK ✔️ api-key
─────────────────────────────────────────────────────────────────────────────
crowdsec-lapi-58cbf76bff-j8jgm:/# cscli bouncer list
─────────────────────────────────────────────────────────────────────────────
Name IP Address Valid Last API pull Type Version Auth Type
─────────────────────────────────────────────────────────────────────────────
crowdsecBouncer ✔️ api-key
TRAEFIK ✔️ api-key
─────────────────────────────────────────────────────────────────────────────
blotus
blotus6mo ago
ok so traefik did not even try to connect to LAPI nothing in the traefik logs ?
ook
ookOP6mo ago
note: I just deleted everything and rebuilt: now I have traefik logs saying the bouncer plugin fails to reach crowdsec service:
DEBUG: CrowdsecBouncerTraefikPlugin: 2025/03/25 11:57:44 handleStreamTicker updateFailure:72 isCrowdsecStreamHealthy:false crowdsecQuery:unreachable url:http://crowdsec-service.crowdsec:8080/v1/decisions/stream?startup=true Get "http://crowdsec-service.crowdsec:8080/v1/decisions/stream?startup=true": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
DEBUG: CrowdsecBouncerTraefikPlugin: 2025/03/25 11:57:44 handleStreamTicker updateFailure:72 isCrowdsecStreamHealthy:false crowdsecQuery:unreachable url:http://crowdsec-service.crowdsec:8080/v1/decisions/stream?startup=true Get "http://crowdsec-service.crowdsec:8080/v1/decisions/stream?startup=true": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
when I take a random pod, I can reach the service:
blotus
blotus6mo ago
do you have any kind of firewalling / network policies / ... in the cluster ? we don't restrict which pods can contact LAPI, so if you can resolve, it should work in theory
ook
ookOP6mo ago
nothing non standard in rancher2 very weird: so from random pod in the same ns than traefik:
bash-4.4$ curl -v http://crowdsec-service.crowdsec:8080/v1/decisions/stream?startup=true
* Trying 10.43.41.177...
* TCP_NODELAY set
* Connected to crowdsec-service.crowdsec (10.43.41.177) port 8080 (#0)
> GET /v1/decisions/stream?startup=true HTTP/1.1
> Host: crowdsec-service.crowdsec:8080
> User-Agent: curl/7.61.1
> Accept: */*
>
< HTTP/1.1 403 Forbidden
< Content-Type: application/json; charset=utf-8
< Date: Tue, 25 Mar 2025 12:00:44 GMT
< Content-Length: 30
<
* Connection #0 to host crowdsec-service.crowdsec left intact
{"message":"access forbidden"}bash-4.4$
bash-4.4$ curl -v http://crowdsec-service.crowdsec:8080/v1/decisions/stream?startup=true
* Trying 10.43.41.177...
* TCP_NODELAY set
* Connected to crowdsec-service.crowdsec (10.43.41.177) port 8080 (#0)
> GET /v1/decisions/stream?startup=true HTTP/1.1
> Host: crowdsec-service.crowdsec:8080
> User-Agent: curl/7.61.1
> Accept: */*
>
< HTTP/1.1 403 Forbidden
< Content-Type: application/json; charset=utf-8
< Date: Tue, 25 Mar 2025 12:00:44 GMT
< Content-Length: 30
<
* Connection #0 to host crowdsec-service.crowdsec left intact
{"message":"access forbidden"}bash-4.4$
but from the traefik pod:
/ # curl -v http://crowdsec-service.crowdsec:8080/v1/decisions/stream?startup=true
* Could not resolve host: crowdsec-service.crowdsec
* shutting down connection #0
curl: (6) Could not resolve host: crowdsec-service.crowdsec
/ # curl -v http://crowdsec-service.crowdsec:8080/v1/decisions/stream?startup=true
* Could not resolve host: crowdsec-service.crowdsec
* shutting down connection #0
curl: (6) Could not resolve host: crowdsec-service.crowdsec
hum… could be a calico issue?
blotus
blotus6mo ago
maybe For the resolution issue, could be something in the traefik pod (eg, a different search domain from what you have in the other pod for some reason) you can maybe try with the full service FQDN
ook
ookOP6mo ago
indeed, I’ll try with the FQDN service FYI I have this configuration for traefik:
dnsConfig:
nameservers:
- 8.8.8.8
dnsPolicy: ClusterFirst
hostNetwork: true
dnsConfig:
nameservers:
- 8.8.8.8
dnsPolicy: ClusterFirst
hostNetwork: true
don’t remember why I added that, it was 6yo ok, it’s a dns issue at traefik level: FQDN doesn’t work on traefik pod, but using the service IP works SVC IP are stable so it could be usable, but I’ll try to solve it before turning to raw IP Thank you blotus, I’ll keep you in touch So, the DNS issue is solved (I removed all the outdated dns and hostNetwork stuff from the traefik pod definition) Now the plugin can resolve the service, but get a 403
DEBUG: CrowdsecBouncerTraefikPlugin: 2025/03/25 19:08:48 ServeHTTP ip:<redactedattacker> isTrusted:false
DEBUG: CrowdsecBouncerTraefikPlugin: 2025/03/25 19:08:48 cache:Get key:<redactedattacker>
DEBUG: CrowdsecBouncerTraefikPlugin: 2025/03/25 19:08:48 ServeHTTP:Get ip:<redactedattacker> isBanned:false cache:miss
DEBUG: CrowdsecBouncerTraefikPlugin: 2025/03/25 19:08:48 ServeHTTP isCrowdsecStreamHealthy:false ip:<redactedattacker> updateFailure:23
DEBUG: CrowdsecBouncerTraefikPlugin: 2025/03/25 19:09:33 cache:Get key:updated
DEBUG: CrowdsecBouncerTraefikPlugin: 2025/03/25 19:09:33 cache:Set key:updated value:f duration:59s
DEBUG: CrowdsecBouncerTraefikPlugin: 2025/03/25 19:09:33 handleStreamTicker updateFailure:23 isCrowdsecStreamHealthy:false crowdsecQuery url:http://crowdsec-service.crowdsec:8080/v1/decisions/stream?startup=true, statusCode:403
DEBUG: CrowdsecBouncerTraefikPlugin: 2025/03/25 19:08:48 ServeHTTP ip:<redactedattacker> isTrusted:false
DEBUG: CrowdsecBouncerTraefikPlugin: 2025/03/25 19:08:48 cache:Get key:<redactedattacker>
DEBUG: CrowdsecBouncerTraefikPlugin: 2025/03/25 19:08:48 ServeHTTP:Get ip:<redactedattacker> isBanned:false cache:miss
DEBUG: CrowdsecBouncerTraefikPlugin: 2025/03/25 19:08:48 ServeHTTP isCrowdsecStreamHealthy:false ip:<redactedattacker> updateFailure:23
DEBUG: CrowdsecBouncerTraefikPlugin: 2025/03/25 19:09:33 cache:Get key:updated
DEBUG: CrowdsecBouncerTraefikPlugin: 2025/03/25 19:09:33 cache:Set key:updated value:f duration:59s
DEBUG: CrowdsecBouncerTraefikPlugin: 2025/03/25 19:09:33 handleStreamTicker updateFailure:23 isCrowdsecStreamHealthy:false crowdsecQuery url:http://crowdsec-service.crowdsec:8080/v1/decisions/stream?startup=true, statusCode:403
I guess the plugin don’t get the lapi shared password. If I understand well, the plugin know nothing of the lapi password, which is passed from the middleware The last API Pull is still null the middleware is configured as following:
spec:
plugin:
bouncer:
crowdsecLapiHost: crowdsec-service.crowdsec:8080
crowdsecLapiKey: <SHAREDLAPIPASSWORD>
crowdsecLapiScheme: http
crowdsecMode: stream
enabled: true
logLevel: DEBUG
spec:
plugin:
bouncer:
crowdsecLapiHost: crowdsec-service.crowdsec:8080
crowdsecLapiKey: <SHAREDLAPIPASSWORD>
crowdsecLapiScheme: http
crowdsecMode: stream
enabled: true
logLevel: DEBUG
am I missing something, @blotus ?
blotus
blotus6mo ago
most likely a bad API key how did you generate the one you are using in the bouncer ?
ook
ookOP6mo ago
fully random 25 chars of digits and letters
blotus
blotus6mo ago
sorry, I meant did you use cscli bouncers add manually, passed it to the LAPI pod with an env var, ... ?
ook
ookOP6mo ago
hum… the same key is in the lapi pod env BOUNCER_KEY_TRAEFIK but I’m pretty sure it’s not the pass given at cscli bouncers add can I generate a new bouncer key or should I destroy and create a new one?
blotus
blotus6mo ago
in the LAPI pod: cscli bouncers delete TRAEFIK then restart the pod, it will recreate the bouncer in the DB automatically with the key provided in the env var I guess you maybe changed the value of the key during your tests ? (the start script cannot detect if the key has changed, so if you change the value in the env var once the bouncer has been created, it will not get updated in the DB)
ook
ookOP6mo ago
I certainly tried some days ago to change the key, indeed
TRAEFIK 10.42.10.229 ✔️ 2025-03-25T19:30:32Z Crowdsec-Bouncer-Traefik-Plugin 1.X.X api-key
TRAEFIK 10.42.10.229 ✔️ 2025-03-25T19:30:32Z Crowdsec-Bouncer-Traefik-Plugin 1.X.X api-key
blotus
blotus6mo ago
better 🙂
ook
ookOP6mo ago
Thank you @blotus ! So it was a mix of a bad DNS setting in the Traefik pod and a bad key configured Let me check a manual ban… A little fear due to the decision pull delay, but it worked! Thanks again
blotus
blotus6mo ago
the default delay is 10s, but you can configure it in the bouncer if you want
ook
ookOP6mo ago
That’s fine for me. Is it possible to mark this post as solved?
blotus
blotus6mo ago
sure /resolve
CrowdSec
CrowdSec6mo ago
Resolving k8s Traefik bouncer: decision not applied This has now been resolved. If you think this is a mistake please run /unresolve
ook
ookOP6mo ago
Perfect! Time to configure recaptcha and eventually redis to share the decisions. Have a good night! Sorry to ping you again, @blotus but I’m surprised of this morning issue: the bouncer no longer was able to reach the LAPI this morning. I didn’t made screen but I saw the previous TRAEFIK bouncer in cscli bouncer list but a TRAEFIK@10.42.10.230 appeared, never pulled. Since the lapi key BOUNCER_KEY_TRAEFIK is still in the env, I did the same thing than last time: destroy all the bouncers then restart the LAPI pod. The traefik pod can reach the LAPI but can’t auth {"message":"access forbidden"} . From the traefik logs in debug, the plugin say:
DEBUG: CrowdsecBouncerTraefikPlugin: 2025/03/27 10:10:06 handleStreamTicker updateFailure:75 isCrowdsecStreamHealthy:false crowdsecQuery:unreachable url:http://crowdsec-service.crowdsec:8080/v1/decisions/stream?startup=true Get "http://crowdsec-service.crowdsec:8080/v1/decisions/stream?startup=true": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
DEBUG: CrowdsecBouncerTraefikPlugin: 2025/03/27 10:10:06 handleStreamTicker updateFailure:75 isCrowdsecStreamHealthy:false crowdsecQuery:unreachable url:http://crowdsec-service.crowdsec:8080/v1/decisions/stream?startup=true Get "http://crowdsec-service.crowdsec:8080/v1/decisions/stream?startup=true": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
what could have gone wrong here? 😕
iiamloz
iiamloz6mo ago
time="2025-03-27T16:28:51Z" level=info msg="127.0.0.1 - [Thu, 27 Mar 2025 16:28:51 UTC] \"HEAD /v1/decisions/stream HTTP/1.1 200 807.423µs \"curl/8.12.1\" \""
time="2025-03-27T16:29:14Z" level=info msg="127.0.0.1 - [Thu, 27 Mar 2025 16:29:14 UTC] \"HEAD /v1/decisions/stream?startup=true HTTP/1.1 200 817.885µs \"curl/8.12.1\" \""
time="2025-03-27T16:31:00Z" level=info msg="127.0.0.1 - [Thu, 27 Mar 2025 16:31:00 UTC] \"GET /v1/decisions/stream?startup=true HTTP/1.1 200 13.828789076s \"curl/8.12.1\" \""
time="2025-03-27T16:31:30Z" level=info msg="127.0.0.1 - [Thu, 27 Mar 2025 16:31:30 UTC] \"HEAD /v1/decisions/stream?startup=true HTTP/1.1 200 945.824µs \"curl/8.12.1\" \""
time="2025-03-27T16:33:07Z" level=info msg="127.0.0.1 - [Thu, 27 Mar 2025 16:33:07 UTC] \"GET /v1/decisions/stream?startup=true HTTP/1.1 200 10.537185766s \"curl/8.12.1\" \""
time="2025-03-27T16:33:34Z" level=info msg="127.0.0.1 - [Thu, 27 Mar 2025 16:33:34 UTC] \"GET /v1/decisions/stream?startup=true HTTP/1.1 200 10.878952939s \"curl/8.12.1\" \""
time="2025-03-27T16:39:21Z" level=info msg="127.0.0.1 - [Thu, 27 Mar 2025 16:39:21 UTC] \"GET /v1/decisions/stream?startup=true HTTP/1.1 200 10.924671899s \"curl/8.12.1\" \""
time="2025-03-27T16:28:51Z" level=info msg="127.0.0.1 - [Thu, 27 Mar 2025 16:28:51 UTC] \"HEAD /v1/decisions/stream HTTP/1.1 200 807.423µs \"curl/8.12.1\" \""
time="2025-03-27T16:29:14Z" level=info msg="127.0.0.1 - [Thu, 27 Mar 2025 16:29:14 UTC] \"HEAD /v1/decisions/stream?startup=true HTTP/1.1 200 817.885µs \"curl/8.12.1\" \""
time="2025-03-27T16:31:00Z" level=info msg="127.0.0.1 - [Thu, 27 Mar 2025 16:31:00 UTC] \"GET /v1/decisions/stream?startup=true HTTP/1.1 200 13.828789076s \"curl/8.12.1\" \""
time="2025-03-27T16:31:30Z" level=info msg="127.0.0.1 - [Thu, 27 Mar 2025 16:31:30 UTC] \"HEAD /v1/decisions/stream?startup=true HTTP/1.1 200 945.824µs \"curl/8.12.1\" \""
time="2025-03-27T16:33:07Z" level=info msg="127.0.0.1 - [Thu, 27 Mar 2025 16:33:07 UTC] \"GET /v1/decisions/stream?startup=true HTTP/1.1 200 10.537185766s \"curl/8.12.1\" \""
time="2025-03-27T16:33:34Z" level=info msg="127.0.0.1 - [Thu, 27 Mar 2025 16:33:34 UTC] \"GET /v1/decisions/stream?startup=true HTTP/1.1 200 10.878952939s \"curl/8.12.1\" \""
time="2025-03-27T16:39:21Z" level=info msg="127.0.0.1 - [Thu, 27 Mar 2025 16:39:21 UTC] \"GET /v1/decisions/stream?startup=true HTTP/1.1 200 10.924671899s \"curl/8.12.1\" \""
Is your cluster running a hard disk or ssd?
ook
ookOP6mo ago
this one was a HDD node, not a SSD I guess I should try to locate on a SSD node?
iiamloz
iiamloz6mo ago
Yeah only because it seems a head request is near instant which means no network problems but when reading from database its slow
ook
ookOP6mo ago
hum, so putting the db on another thing than sqlite could help as well. Which backend do you support?
iiamloz
iiamloz6mo ago
the major ones like mariadb, postgres, mysql but we prefer to say postgres
ook
ookOP6mo ago
which is the best of these 3 ^^
iiamloz
iiamloz6mo ago
postgres we had problems with mysql and mariadb in past if you want to setup clustering but postgres has always had no issues
ook
ookOP6mo ago
ok, I’ll evict the lapi from hdd nodes, and eventually try to create a PG instance ok so moved to another node, but there’s no decisions at all: is there a way to force sync of decisions? I guess it was the subscribed blocklists
iiamloz
iiamloz6mo ago
These will be classed as new entites did you enroll them / accept if they are in console pending? Unless there is some k8s way to move data but are you using sqlire or pg?
ook
ookOP6mo ago
indeed, I just validate the enroll sqlite for now, but I’ll certainly create a pg instance it'll be more stable

Did you find this page helpful?