CrowdSec Parser for Stalwart Logs

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.

Hello… is anybody out there? :thinking:

Seems not much people reading, but I just want to mention I had the same, only with Exim.
I did asked Claude (you also mentioned using AI) and that was a big help for me, and in the end had an improved version for it.

You can see with the command “cscli metrics” and than look under Parser Metrics.

Good luck :slight_smile:

Thank you. I am also supriesed that nobody answers. Are there no developers or experts in this fourm?

The metrcs show:

# docker exec crowdsec cscli metrics
+----------------------------------------------------------------------------------------------------------------------------------+
| Acquisition Metrics                                                                                                              |
+----------------------------------------+------------+--------------+----------------+------------------------+-------------------+
| Source                                 | Lines read | Lines parsed | Lines unparsed | Lines poured to bucket | Lines whitelisted |
+----------------------------------------+------------+--------------+----------------+------------------------+-------------------+
| file:/remotelogs/stalwart/stalwart.log | 155        | 155          | -              | -                      | -                 |
| file:/var/log/caddy/access.log         | 45         | 45           | -              | 20                     | -                 |
+----------------------------------------+------------+--------------+----------------+------------------------+-------------------+

[...]

+---------------------------------------------------------------+
| Parser Metrics                                                |
+------------------------------------+------+--------+----------+
| Parsers                            | Hits | Parsed | Unparsed |
+------------------------------------+------+--------+----------+
| child-crowdsecurity/http-logs      | 135  | 90     | 45       |
| child-stalwart/parse-extended      | 155  | 155    | -        |
| child-stalwart/parse-logs          | 200  | 155    | 45       |
| crowdsecurity/caddy-logs           | 45   | 45     | -        |
| crowdsecurity/dateparse-enrich     | 45   | 45     | -        |
| crowdsecurity/geoip-enrich         | 45   | 45     | -        |
| crowdsecurity/http-logs            | 45   | 45     | -        |
| crowdsecurity/nextcloud-whitelist  | 45   | 45     | -        |
| crowdsecurity/non-syslog           | 45   | 45     | -        |
| crowdsecurity/public-dns-allowlist | 200  | 200    | -        |
| crowdsecurity/whitelists           | 200  | 200    | -        |
| stalwart/parse-extended            | 155  | 155    | -        |
| stalwart/parse-logs                | 200  | 155    | 45       |
| whitelist_immich_server            | 200  | 200    | -        |
+------------------------------------+------+--------+----------+

[...]

I hope this is good news. Sometimes I am not shure how to interpret the activities of CrowdSec.