add crowdsec

This commit is contained in:
2026-05-10 00:07:06 +04:00
parent 54e3854c0d
commit e11b03ebaf
20 changed files with 376 additions and 57 deletions
+12
View File
@@ -0,0 +1,12 @@
############# Bouncer keys #############
# Generate with: openssl rand -hex 32
# These are PRE-SEEDED into CrowdSec on first boot. Use the same value here
# and in caddy/.env (CADDY) and the host firewall bouncer config (FW).
CROWDSEC_BOUNCER_KEY_CADDY=
CROWDSEC_BOUNCER_KEY_FW=
############# Console enrollment #############
# Enroll key from https://app.crowdsec.net (free).
# Leave blank to run without Console (no community blocklist subscriptions).
CROWDSEC_ENROLL_KEY=
CROWDSEC_ENROLL_INSTANCE_NAME=
+7
View File
@@ -0,0 +1,7 @@
appsec_configs:
- crowdsecurity/appsec-default
labels:
type: appsec
listen_addr: 0.0.0.0:7422
source: appsec
name: caddy-appsec
+8
View File
@@ -0,0 +1,8 @@
source: docker
container_name:
- caddy
labels:
type: caddy
follow_stdout: true
follow_stderr: true
check_interval: 5s
+26
View File
@@ -0,0 +1,26 @@
source: docker
container_name:
- gitea
labels:
type: gitea
follow_stdout: true
follow_stderr: true
check_interval: 5s
---
source: docker
container_name:
- vaultwarden
labels:
type: vaultwarden
follow_stdout: true
follow_stderr: true
check_interval: 5s
---
source: docker
container_name:
- stalwart
labels:
type: stalwart
follow_stdout: true
follow_stderr: true
check_interval: 5s
+5
View File
@@ -0,0 +1,5 @@
source: journalctl
journalctl_filter:
- "_SYSTEMD_UNIT=ssh.service"
labels:
type: syslog
+3
View File
@@ -0,0 +1,3 @@
/db/*
/config/*
!.gitkeep
View File
View File
+51
View File
@@ -0,0 +1,51 @@
networks:
caddy:
name: caddy
driver: bridge
external: true
services:
crowdsec:
image: crowdsecurity/crowdsec:latest-debian
container_name: crowdsec
restart: unless-stopped
labels:
- "com.centurylinklabs.watchtower.enable=true"
environment:
TZ: "Etc/UTC"
COLLECTIONS: >-
crowdsecurity/linux
crowdsecurity/caddy
crowdsecurity/http-cve
crowdsecurity/sshd
crowdsecurity/whitelist-good-actors
crowdsecurity/appsec-virtual-patching
crowdsecurity/appsec-generic-rules
LePresidente/gitea
Dominic-Wagner/vaultwarden
BOUNCER_KEY_caddy: "${CROWDSEC_BOUNCER_KEY_CADDY}"
BOUNCER_KEY_firewall: "${CROWDSEC_BOUNCER_KEY_FW}"
ENROLL_KEY: "${CROWDSEC_ENROLL_KEY:-}"
ENROLL_INSTANCE_NAME: "${CROWDSEC_ENROLL_INSTANCE_NAME:-aykhans-prod}"
ports:
- "127.0.0.1:18080:8080"
networks:
- caddy
volumes:
- ./data/db:/var/lib/crowdsec/data
- ./data/config:/etc/crowdsec
- ./acquis.d:/etc/crowdsec/acquis.d:ro
- ./parsers/s00-raw/stalwart-logs.yaml:/etc/crowdsec/parsers/s00-raw/stalwart-logs.yaml:ro
- ./parsers/s01-parse/stalwart-logs-extended.yaml:/etc/crowdsec/parsers/s01-parse/stalwart-logs-extended.yaml:ro
- ./parsers/s02-enrich/whitelist-trusted.yaml:/etc/crowdsec/parsers/s02-enrich/whitelist-trusted.yaml:ro
- ./scenarios/stalwart-smtp-bruteforce.yaml:/etc/crowdsec/scenarios/stalwart-smtp-bruteforce.yaml:ro
- ./scenarios/stalwart-auth-bruteforce.yaml:/etc/crowdsec/scenarios/stalwart-auth-bruteforce.yaml:ro
- /var/log/journal:/var/log/journal:ro
- /run/log/journal:/run/log/journal:ro
- /etc/machine-id:/etc/machine-id:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "3"
@@ -0,0 +1,10 @@
name: stalwart/parse-logs
description: Raw parser for Stalwart logs
stage: s00-raw
onsuccess: next_stage
filter: "evt.Parsed.program == 'stalwart' || evt.Line.Labels.type == 'stalwart'"
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})?$'
@@ -0,0 +1,15 @@
name: stalwart/parse-extended
description: Parse Stalwart logs including key fields without kv parser
stage: s01-parse
onsuccess: next_stage
filter: "evt.Parsed.program == 'stalwart' || evt.Line.Labels.type == 'stalwart'"
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}")?.*$'
statics:
- meta: source_ip
expression: evt.Parsed.remoteIp
- meta: service
value: stalwart
@@ -0,0 +1,11 @@
name: aykhans/whitelist-trusted
description: Trusted operator IPs and Docker private network ranges
whitelist:
reason: "operator + internal docker networks"
ip:
- "127.0.0.1"
- "::1"
cidr:
- "10.0.0.0/8"
- "172.16.0.0/12"
- "192.168.0.0/16"
@@ -0,0 +1,13 @@
type: leaky
name: aykhans/stalwart-auth-bruteforce
description: Detect SMTP/IMAP/POP3 authentication brute force on Stalwart
filter: |
evt.Parsed.event_type == "auth.failed"
groupby: evt.Meta.source_ip
capacity: 3
leakspeed: 10m
blackhole: 1h
labels:
type: bruteforce
service: stalwart
remediation: true
@@ -0,0 +1,17 @@
type: leaky
name: stalwart/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.Meta.source_ip
capacity: 5
leakspeed: 10m
blackhole: 1h
labels:
type: attack
service: smtp
remediation: true