nftables IP ban based on appsec?

I've tried to search for support threads here on discord, but can't really find anything. I've also tried to read the docs and asked chatgpt (increadiably useless, but was worth a try) but I feel like I'm missing something fundamental here. What I want: - AppSec triggered from traefik to add an IP block on nftables. My setup: - Ubuntu server - nftables in front of a traefik instance - crowdsec installed, listening on port 8080, appsec running listening on port 7422 - crowdsec-bouncer-traefik-plugin installed and enabled (crowdsecMode: appsec) - crowdsec-firewall-bouncer When I manually add a decision sudo cscli decisions add -i <client-up> -t ban -d 1m I'm locked out directly When I run "curl -vk "https://<server domain>/?id=%27%20OR%201%3D1--" I can see the following in my traefik logs. DEBUG: CrowdsecBouncerTraefikPlugin: 2025/09/21 12:25:52 ServeHTTP ip:<client computer> isTrusted:false DEBUG: CrowdsecBouncerTraefikPlugin: 2025/09/21 12:25:52 handleNextServeHTTP ip:<client computer> isWaf:true appsecQuery statusCode:403 10.0.0.169 - - [21/Sep/2025:12:25:52 +0000] "GET /?id=%27%20OR%201%3D1-- HTTP/2.0" 403 0 "-" "curl/8.11.1" 61 "next-router@file" "-" 67ms cscli alert list shows:
╭────┬───────────────┬───────────────────────────────────────────────────────┬─────────┬────┬───────────┬──────────────────────╮
│ ID │ value │ reason │ country │ as │ decisions │ created_at │
├────┼───────────────┼───────────────────────────────────────────────────────┼─────────┼────┼───────────┼──────────────────────┤
│ 51 │ Ip:<client computer> │ anomaly score block: sql_injection: 10, anomaly: 10, │ │ │ │ 2025-09-21T12:25:52Z
╭────┬───────────────┬───────────────────────────────────────────────────────┬─────────┬────┬───────────┬──────────────────────╮
│ ID │ value │ reason │ country │ as │ decisions │ created_at │
├────┼───────────────┼───────────────────────────────────────────────────────┼─────────┼────┼───────────┼──────────────────────┤
│ 51 │ Ip:<client computer> │ anomaly score block: sql_injection: 10, anomaly: 10, │ │ │ │ 2025-09-21T12:25:52Z
So AppSec seems to do what I want. But decisions is empty. My understanding of this is that there's an alert created based on the AppSec trigger, but no decision is matched. SO nftables will not block anything.
5 Replies
CrowdSec
CrowdSec2w ago
Important Information
Thank you for getting in touch with your support request. To expedite a swift resolution, could you kindly provide the following information? Rest assured, we will respond promptly, and we greatly appreciate your patience. While you wait, please check the links below to see if this issue has been previously addressed. If you have managed to resolve it, please use run the command /resolve or press the green resolve button below.
Log Files
If you possess any log files that you believe could be beneficial, please include them at this time. By default, CrowdSec logs to /var/log/, where you will discover a corresponding log file for each component.
Guide Followed (CrowdSec Official)
If you have diligently followed one of our guides and hit a roadblock, please share the guide with us. This will help us assess if any adjustments are necessary to assist you further.
Screenshots
Please forward any screenshots depicting errors you encounter. Your visuals will provide us with a clear view of the issues you are facing.
© Created By WhyAydan for CrowdSec ❤️
wutanc
wutancOP2w ago
My undestanding of this is that the appsec.yaml controls what appsec_configs files are loaded. My config should load the custom/appsec-hybrid file. This should trigger an outofband alert when I trigger crowdsecurity/appsec-generic-test, i.e. curl <server-domain>/crowdsec-test-NtktlJHV4TfBSK3wvlhiOBnl. This in turn should trigger the scenarios/custom-appsec.yaml file that should trigger the nftable bouncer if the filter matches. But nothing of this seems to happen. Is there any obvious misunderstandings I've made here? Am I just completely wrong here? If so, where can I read to a better understanding of this? I feel like I must be missing something truly obvious in the docs. (Really sorry for the huge post. Not sure how to cut it down or if I'm missing something I should include) After this I tried adding a scenarios/custom-appsec.yaml file looking something like this below. (I've played around with the filter a lot-)
type: leaky
filter: evt.Parsed.source == 'crowdsec-appsec'
name: crowdsecurity/crowdsec-appsec-outofband
blackhole: 2m
leakspeed: 30s
capacity: 1
labels:
type: exploit
remediation: true
type: leaky
filter: evt.Parsed.source == 'crowdsec-appsec'
name: crowdsecurity/crowdsec-appsec-outofband
blackhole: 2m
leakspeed: 30s
capacity: 1
labels:
type: exploit
remediation: true
As well as a appsec-configs/custom-appsec.yaml file. I've played aruond with what inbound and outofband rules I have.
name: custom/appsec-hybrid
default_remediation: ban
log_level: debug

inband_rules:
- crowdsecurity/crs
- crowdsecurity/base-config
- crowdsecurity/vpatch-*
- crowdsecurity/generic-*

outofband_rules:
- crowdsecurity/appsec-generic-test
# - crowdsecurity/experimental-*
name: custom/appsec-hybrid
default_remediation: ban
log_level: debug

inband_rules:
- crowdsecurity/crs
- crowdsecurity/base-config
- crowdsecurity/vpatch-*
- crowdsecurity/generic-*

outofband_rules:
- crowdsecurity/appsec-generic-test
# - crowdsecurity/experimental-*
And lastly my appsec.yaml file:
appsec_configs:
- custom/appsec-hybrid
labels:
type: appsec
log_type: appsec-block
listen_addr: 127.0.0.1:7422
source: appsecf
appsec_configs:
- custom/appsec-hybrid
labels:
type: appsec
log_type: appsec-block
listen_addr: 127.0.0.1:7422
source: appsecf
(also sorry for the jumbled post. I was over the 2000 char limit) Not sure if it helps at all. But this is a big of my debug log that seems to show what's going on, and where it fails. I'm just not sure why it fails.
time="2025-09-21T21:36:15+02:00" level=debug msg="custom rule for event, setting name: crowdsecurity/appsec-generic-test, version: 0.3, hash: 1ffdb3af4b6e18985b8d457e6484e749bb04629c8e73fa6df656db74898cfb9b" runner_uuid=612b69bb-c322-49d7-a6d3-c28ff9c0fcea type=appsec
time="2025-09-21T21:36:15+02:00" level=debug msg="outband rules matched : 3952763708" runner_uuid=612b69bb-c322-49d7-a6d3-c28ff9c0fcea type=appsec
time="2025-09-21T21:36:15+02:00" level=debug msg="Transaction finished" band=outband chain_rule_id=749632433 is_interrupted=true rule_id=3952763708 runner_uuid=612b69bb-c322-49d7-a6d3-c28ff9c0fcea status=403 tx_id=85b0d987-1c7a-4a9e-b2d4-14e4d2fb41c9 type=appsec variable=REQUEST_FILENAME
time="2025-09-21T21:36:15+02:00" level=debug msg="Event leaving node : ko (failed filter)" id=throbbing-dust name=crowdsecurity/syslog-logs stage=s00-raw
time="2025-09-21T21:36:15+02:00" level=debug msg="+ Processing 4 statics" id=wispy-sun name=crowdsecurity/non-syslog stage=s00-raw
time="2025-09-21T21:36:15+02:00" level=debug msg=".Parsed[message] = 'dummy-appsec-data'" id=wispy-sun name=crowdsecurity/non-syslog stage=s00-raw
time="2025-09-21T21:36:15+02:00" level=debug msg=".Parsed[program] = 'appsec'" id=wispy-sun name=crowdsecurity/non-syslog stage=s00-raw
time="2025-09-21T21:36:15+02:00" level=debug msg=".Meta[datasource_path] = 'appsec'" id=wispy-sun name=crowdsecurity/non-syslog stage=s00-raw
time="2025-09-21T21:36:15+02:00" level=debug msg=".Meta[datasource_type] = 'appsec'" id=wispy-sun name=crowdsecurity/non-syslog stage=s00-raw
time="2025-09-21T21:36:15+02:00" level=debug msg="custom rule for event, setting name: crowdsecurity/appsec-generic-test, version: 0.3, hash: 1ffdb3af4b6e18985b8d457e6484e749bb04629c8e73fa6df656db74898cfb9b" runner_uuid=612b69bb-c322-49d7-a6d3-c28ff9c0fcea type=appsec
time="2025-09-21T21:36:15+02:00" level=debug msg="outband rules matched : 3952763708" runner_uuid=612b69bb-c322-49d7-a6d3-c28ff9c0fcea type=appsec
time="2025-09-21T21:36:15+02:00" level=debug msg="Transaction finished" band=outband chain_rule_id=749632433 is_interrupted=true rule_id=3952763708 runner_uuid=612b69bb-c322-49d7-a6d3-c28ff9c0fcea status=403 tx_id=85b0d987-1c7a-4a9e-b2d4-14e4d2fb41c9 type=appsec variable=REQUEST_FILENAME
time="2025-09-21T21:36:15+02:00" level=debug msg="Event leaving node : ko (failed filter)" id=throbbing-dust name=crowdsecurity/syslog-logs stage=s00-raw
time="2025-09-21T21:36:15+02:00" level=debug msg="+ Processing 4 statics" id=wispy-sun name=crowdsecurity/non-syslog stage=s00-raw
time="2025-09-21T21:36:15+02:00" level=debug msg=".Parsed[message] = 'dummy-appsec-data'" id=wispy-sun name=crowdsecurity/non-syslog stage=s00-raw
time="2025-09-21T21:36:15+02:00" level=debug msg=".Parsed[program] = 'appsec'" id=wispy-sun name=crowdsecurity/non-syslog stage=s00-raw
time="2025-09-21T21:36:15+02:00" level=debug msg=".Meta[datasource_path] = 'appsec'" id=wispy-sun name=crowdsecurity/non-syslog stage=s00-raw
time="2025-09-21T21:36:15+02:00" level=debug msg=".Meta[datasource_type] = 'appsec'" id=wispy-sun name=crowdsecurity/non-syslog stage=s00-raw
time="2025-09-21T21:36:15+02:00" level=debug msg="Event leaving node : ok" id=wispy-sun name=crowdsecurity/non-syslog stage=s00-raw
time="2025-09-21T21:36:15+02:00" level=debug msg="move Event from stage s00-raw to s01-parse" id=wispy-sun name=crowdsecurity/non-syslog stage=s00-raw
time="2025-09-21T21:36:15+02:00" level=debug msg="node successful, stop end stage s00-raw" node-name=wispy-sun stage=s00-raw
time="2025-09-21T21:36:15+02:00" level=debug msg="Event leaving node : ko (failed filter)" id=old-cherry name=crowdsecurity/sshd-logs stage=s01-parse
time="2025-09-21T21:36:15+02:00" level=debug msg="Log didn't finish stage s01-parse"
time="2025-09-21T21:36:15+02:00" level=debug msg="Event leaving node : ok" id=wispy-sun name=crowdsecurity/non-syslog stage=s00-raw
time="2025-09-21T21:36:15+02:00" level=debug msg="move Event from stage s00-raw to s01-parse" id=wispy-sun name=crowdsecurity/non-syslog stage=s00-raw
time="2025-09-21T21:36:15+02:00" level=debug msg="node successful, stop end stage s00-raw" node-name=wispy-sun stage=s00-raw
time="2025-09-21T21:36:15+02:00" level=debug msg="Event leaving node : ko (failed filter)" id=old-cherry name=crowdsecurity/sshd-logs stage=s01-parse
time="2025-09-21T21:36:15+02:00" level=debug msg="Log didn't finish stage s01-parse"
It seems like it's not running my scenario at all. But not sure why
iiamloz
iiamloz2w ago
This would be unlikely just make sure if you run cscli parsers list that you have the appsec parser so it does to the scenarios.
iiamloz
iiamloz2w ago
Collections, AppSec Rules & Configurations | CrowdSec Hub
Manage collections, configurations, remediation components, and AppSec rules with CrowdSec Hub. Streamline security with tools and integrations for enhanced protection.
wutanc
wutancOP2w ago
And I just got it working. I missed your response here 🙂 But YES. it was indeed a missed parser. I have no idea how I missed that 😐 The last logs I pasted made me realize I never had any logs from the scenario I was expecting, just the non-syslog once. That made me read up on parsers and realized I actually didn't have an appsec parser. Installed it, started seeing logs, tweaked my filter to something working again and I was locked out of my server 😄 Success This was a some what frustrating debug session, but I learnt a lot Didn't originally know what I was supposed to see in the logs, making it much harder Time to deploy this thing and get some real world logs I Think 😄 Ok, as far as I can tell it's all working as expected now. Thanks for the push Loz 😄

Did you find this page helpful?