2.687
Hello CrowdSec Community,
I’ve been using CrowdSec as an extension in the reverse proxy Caddy for quite some time, but I’m new to the community. Everything is running in a Docker Compose instance with its own MacVLAN. In my small, private home lab, I’ve installed Stalwart Mail in Docker, which generates a continuous log file called stalwart.log. I’ve built a CrowdSec parser using AI, but I’d like to know if it’s correct.
I’ve been using CrowdSec for a while now, but I’d like your feedback on whether it’s working correctly. In the stalwart.log file, I find the following log lines, for example, because Stalwart also has its own security measures, which I would like to address with CrowdSec:
2026-04-26T00:17:59Z INFO Banned due to scan (security.scan-ban) listenerId = "submissions", localPort = 465, remoteIp = 104.248.203.156, remotePort = 47964, remoteIp = 104.248.203.156, reason = "Invalid SMTP command"
To address this, I added the following entry to the acquise.yaml file:
[...]
---
filenames:
- /remotelogs/stalwart/stalwart.log
labels:
type: stalwart
I also created the file /parsers/s00-raw/stalwart-logs.yaml created:
name: stalwart/parse-logs
description: Raw parser for Stalwart logs
stage: s00-raw
onsuccess: next_stage
nodes:
- grok:
apply_on: Line.Raw
pattern: '^%{TIMESTAMP_ISO8601:timestamp}\s+%{WORD:log_level}\s+%{DATA:message_text}\s*\(%{DATA:event_type}\)\s*(%{GREEDYDATA:kvpairs})?$'
Another file /parsers/s01-parse/stalwart-logs-extended.yaml looks like this:
Eine weitere Datei /parsers/s01-parse/stalwart-logs-extended.yaml sieht so aus:
name: stalwart/parse-extended
description: Parse Stalwart logs including key fields without kv parser
stage: s01-parse
onsuccess: next_stage
# This Parser extracts:
# - timestamp
# - log_level
# - message_text
# - event_type
# - listenerId
# - localPort
# - remoteIp
# - remotePort
# - reason
nodes:
- grok:
apply_on: Line.Raw
pattern: '^%{TIMESTAMP_ISO8601:timestamp}\s+%{WORD:log_level}\s+%{DATA:message_text}\s+\(%{DATA:event_type}\)\s*(?:listenerId\s*=\s*"%{DATA:listenerId}",\s*)?(?:localPort\s*=\s*%{INT:localPort},\s*)?(?:remoteIp\s*=\s*%{IP:remoteIp},\s*)?(?:remotePort\s*=\s*%{INT:remotePort},\s*)?(?:reason\s*=\s*"%{DATA:reason}")?.*$'
Finally there is /scenarios/stalwart-smtp-bruteforce.yaml:
type: leaky
name: stalwart/smtp-smtp-bruteforce
description: Detect SMTP bruteforce and scanners on Stalwart logs
filter: |
evt.Parsed.event_type in [
"smtp.invalid-ehlo",
"smtp.auth-not-allowed",
"smtp.auth-mechanism-not-supported"
]
groupby: evt.Parsed.source_ip
capacity: 5
leakspeed: 10m
blackhole: 1h
labels:
type: attack
service: smtp
remediation: true
My question for the parser experts is whether this is correct and can work. At least when starting Stalwart, there are no error messages.
Thank you for your help.
Regards,
Mic.