feat(crowdsec): Add custom CrowdSec scenarios package for SecuBox

- Add secubox-app-crowdsec-custom package with:
  - HTTP auth bruteforce detection
  - Path scanning detection
  - LuCI/uhttpd auth monitoring
  - Trusted IP whitelist for private networks
- Fix Lyrion Docker image path to ghcr.io/lms-community/lyrionmusicserver:stable

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
CyberMind-FR 2026-01-22 14:50:36 +01:00
parent a23038f779
commit 3e52444a73
11 changed files with 300 additions and 2 deletions

View File

@ -0,0 +1,113 @@
# Copyright (C) 2024-2025 CyberMind.fr
# Licensed under Apache-2.0
include $(TOPDIR)/rules.mk
PKG_NAME:=secubox-app-crowdsec-custom
PKG_VERSION:=1.0.0
PKG_RELEASE:=1
PKG_ARCH:=all
PKG_LICENSE:=Apache-2.0
PKG_MAINTAINER:=CyberMind <contact@cybermind.fr>
include $(INCLUDE_DIR)/package.mk
define Package/secubox-app-crowdsec-custom
SECTION:=secubox
CATEGORY:=SecuBox
TITLE:=CrowdSec Custom Scenarios for SecuBox
DEPENDS:=+crowdsec +crowdsec-firewall-bouncer
PKGARCH:=all
PROVIDES:=secubox-crowdsec-custom
endef
define Package/secubox-app-crowdsec-custom/description
Custom CrowdSec configurations for SecuBox web interface protection.
Includes:
- HTTP authentication bruteforce detection
- Path scanning/enumeration detection
- LuCI/uhttpd auth failure monitoring
- Nginx reverse proxy monitoring (if used)
- Whitelist for trusted networks
endef
define Build/Compile
endef
define Package/secubox-app-crowdsec-custom/install
# Acquisition configs
$(INSTALL_DIR) $(1)/etc/crowdsec/acquis.d
$(INSTALL_DATA) ./files/acquis.d/secubox-uhttpd.yaml $(1)/etc/crowdsec/acquis.d/
$(INSTALL_DATA) ./files/acquis.d/secubox-nginx.yaml $(1)/etc/crowdsec/acquis.d/
$(INSTALL_DATA) ./files/acquis.d/secubox-auth.yaml $(1)/etc/crowdsec/acquis.d/
# Custom parsers
$(INSTALL_DIR) $(1)/etc/crowdsec/parsers/s01-parse
$(INSTALL_DATA) ./files/parsers/s01-parse/secubox-luci-auth.yaml $(1)/etc/crowdsec/parsers/s01-parse/
$(INSTALL_DIR) $(1)/etc/crowdsec/parsers/s02-enrich
$(INSTALL_DATA) ./files/parsers/s02-enrich/secubox-whitelist.yaml $(1)/etc/crowdsec/parsers/s02-enrich/
# Custom scenarios
$(INSTALL_DIR) $(1)/etc/crowdsec/scenarios
$(INSTALL_DATA) ./files/scenarios/secubox-auth-bruteforce.yaml $(1)/etc/crowdsec/scenarios/
$(INSTALL_DATA) ./files/scenarios/secubox-http-bruteforce.yaml $(1)/etc/crowdsec/scenarios/
# UCI defaults for first boot setup
$(INSTALL_DIR) $(1)/etc/uci-defaults
$(INSTALL_BIN) ./files/99-secubox-app-crowdsec-custom $(1)/etc/uci-defaults/
endef
define Package/secubox-app-crowdsec-custom/postinst
#!/bin/sh
[ -n "$${IPKG_INSTROOT}" ] || {
echo "Installing CrowdSec collections for SecuBox..."
# Install standard collections
cscli collections install crowdsecurity/linux 2>/dev/null || true
cscli collections install crowdsecurity/sshd 2>/dev/null || true
cscli collections install crowdsecurity/base-http-scenarios 2>/dev/null || true
cscli collections install crowdsecurity/http-cve 2>/dev/null || true
cscli collections install crowdsecurity/nginx 2>/dev/null || true
cscli collections install crowdsecurity/http-dos 2>/dev/null || true
# Install parsers
cscli parsers install crowdsecurity/syslog-logs 2>/dev/null || true
cscli parsers install crowdsecurity/http-logs 2>/dev/null || true
cscli parsers install crowdsecurity/nginx-logs 2>/dev/null || true
# Run uci-defaults
/etc/uci-defaults/99-secubox-app-crowdsec-custom 2>/dev/null || true
# Restart CrowdSec to load new configs
/etc/init.d/crowdsec restart 2>/dev/null || true
sleep 2
# Restart bouncer
if [ -f /etc/init.d/crowdsec-firewall-bouncer ]; then
/etc/init.d/crowdsec-firewall-bouncer restart 2>/dev/null || true
fi
echo ""
echo "SecuBox CrowdSec protection installed!"
echo "Protected paths: /secubox/, /cgi-bin/luci, /ubus"
echo ""
echo "Useful commands:"
echo " cscli metrics - View detection metrics"
echo " cscli alerts list - View security alerts"
echo " cscli decisions list - View active bans"
}
exit 0
endef
define Package/secubox-app-crowdsec-custom/postrm
#!/bin/sh
[ -n "$${IPKG_INSTROOT}" ] || {
# Restart CrowdSec to unload configs
/etc/init.d/crowdsec restart 2>/dev/null || true
echo "SecuBox CrowdSec custom configs removed"
}
exit 0
endef
$(eval $(call BuildPackage,secubox-app-crowdsec-custom))

View File

@ -0,0 +1,36 @@
#!/bin/sh
# SecuBox CrowdSec Custom - First boot setup
# Configures logging for CrowdSec monitoring
# Enable uhttpd syslog logging
if command -v uci >/dev/null 2>&1; then
uci set uhttpd.main.syslog='1' 2>/dev/null
uci commit uhttpd 2>/dev/null
fi
# Ensure syslog writes to file for CrowdSec
if [ -f /etc/config/system ]; then
uci set system.@system[0].log_file='/var/log/messages' 2>/dev/null
uci set system.@system[0].log_size='512' 2>/dev/null
uci commit system 2>/dev/null
fi
# Restart logging service
/etc/init.d/log restart 2>/dev/null || true
# Restart uhttpd to apply logging changes
/etc/init.d/uhttpd restart 2>/dev/null || true
# Register firewall bouncer if not already registered
if [ -f /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml ]; then
if command -v cscli >/dev/null 2>&1; then
if ! cscli bouncers list 2>/dev/null | grep -q "firewall-bouncer"; then
API_KEY=$(cscli bouncers add firewall-bouncer -o raw 2>/dev/null)
if [ -n "$API_KEY" ]; then
sed -i "s/^api_key:.*/api_key: $API_KEY/" /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml
fi
fi
fi
fi
exit 0

View File

@ -0,0 +1,17 @@
# CrowdSec acquisition for SecuBox/LuCI authentication
# Monitors syslog for auth failures
# Monitor OpenWrt syslog
source: file
filenames:
- /var/log/messages
- /tmp/log/messages
labels:
type: syslog
---
# Monitor auth.log if available
source: file
filenames:
- /var/log/auth.log
labels:
type: syslog

View File

@ -0,0 +1,9 @@
# CrowdSec acquisition for nginx reverse proxy (if used)
# Monitors nginx logs for web attacks
filenames:
- /var/log/nginx/access.log
- /var/log/nginx/error.log
- /var/log/nginx/*access*.log
labels:
type: nginx

View File

@ -0,0 +1,8 @@
# CrowdSec acquisition for SecuBox web interface (uhttpd)
# Monitors uhttpd logs for web attacks
filenames:
- /var/log/uhttpd.log
- /tmp/log/uhttpd.log
labels:
type: syslog

View File

@ -0,0 +1,43 @@
# CrowdSec parser for SecuBox/LuCI authentication logs
# Parses authentication events from uhttpd, luci, and rpcd
onsuccess: next_stage
name: secubox/luci-auth-logs
description: "Parse SecuBox/LuCI authentication events"
filter: "evt.Parsed.program == 'uhttpd' || evt.Parsed.program == 'luci' || evt.Parsed.program == 'rpcd'"
grok:
pattern: "%{GREEDYDATA:message}"
apply_on: message
statics:
- meta: log_type
value: luci_auth
- meta: service
value: secubox
---
# Parse LuCI login failures
onsuccess: next_stage
name: secubox/luci-auth-failure
description: "Parse LuCI authentication failures"
filter: "evt.Parsed.program == 'luci' && evt.Parsed.message contains 'auth'"
grok:
pattern: "luci: %{WORD:action} from %{IP:source_ip}.*(?:failed|denied|invalid)"
apply_on: message
statics:
- meta: auth_success
value: "false"
- meta: source_ip
expression: evt.Parsed.source_ip
---
# Parse uhttpd/rpcd auth attempts
onsuccess: next_stage
name: secubox/uhttpd-auth
description: "Parse uhttpd authentication events"
filter: "evt.Parsed.program == 'uhttpd' || evt.Parsed.program == 'rpcd'"
grok:
pattern: "%{IP:source_ip}.*(?:login|auth|session).*(?:failed|denied|invalid|error)"
apply_on: message
statics:
- meta: auth_success
value: "false"
- meta: log_type
value: luci_auth

View File

@ -0,0 +1,18 @@
# CrowdSec whitelist for SecuBox trusted networks
# Prevents banning of internal/trusted IPs
name: crowdsecurity/secubox-whitelist
description: "Whitelist trusted IPs for SecuBox admin access"
whitelist:
reason: "SecuBox trusted network"
ip:
# Localhost
- "127.0.0.1"
- "::1"
cidr:
# Private networks (RFC1918)
- "192.168.0.0/16"
- "172.16.0.0/12"
- "10.0.0.0/8"
# Add custom admin IPs here if needed
# - "YOUR_ADMIN_IP/32"

View File

@ -0,0 +1,15 @@
# CrowdSec scenario for SecuBox/LuCI authentication bruteforce
# Detects repeated authentication failures
type: leaky
name: secubox/luci-auth-bruteforce
description: "Detect bruteforce attempts on SecuBox/LuCI web interface"
filter: "evt.Meta.log_type == 'luci_auth' && evt.Meta.auth_success == 'false'"
groupby: evt.Meta.source_ip
capacity: 5
leakspeed: 30s
blackhole: 5m
labels:
service: secubox
type: bruteforce
remediation: true

View File

@ -0,0 +1,39 @@
# CrowdSec scenario for SecuBox HTTP authentication bruteforce
# Detects repeated 401/403 errors indicating auth failures
type: leaky
name: secubox/http-auth-bruteforce
description: "Detect HTTP authentication bruteforce on SecuBox web interface"
filter: |
evt.Meta.http_status in ['401', '403'] &&
evt.Parsed.request contains '/cgi-bin/luci' ||
evt.Parsed.request contains '/secubox/' ||
evt.Parsed.request contains '/ubus'
groupby: evt.Meta.source_ip
capacity: 5
leakspeed: 30s
blackhole: 5m
labels:
service: secubox
type: http_bruteforce
remediation: true
---
# Detect path scanning/enumeration
type: leaky
name: secubox/path-scanning
description: "Detect path scanning on SecuBox web interface"
filter: |
evt.Meta.http_status == '404' &&
(evt.Parsed.request contains '/secubox/' ||
evt.Parsed.request contains '/cgi-bin/' ||
evt.Parsed.request contains '/admin' ||
evt.Parsed.request contains '/wp-' ||
evt.Parsed.request contains '.php')
groupby: evt.Meta.source_ip
capacity: 20
leakspeed: 10s
blackhole: 10m
labels:
service: secubox
type: path_scan
remediation: true

View File

@ -1,7 +1,7 @@
config lyrion 'main'
option enabled '0'
option runtime 'auto'
option image 'ghcr.io/lyrion/lyrion:latest'
option image 'ghcr.io/lms-community/lyrionmusicserver:stable'
option data_path '/srv/lyrion'
option media_path '/srv/media'
option port '9000'

View File

@ -49,7 +49,7 @@ uci_set() { uci set ${CONFIG}.main.$1="$2" && uci commit ${CONFIG}; }
# Load configuration with defaults
load_config() {
runtime="$(uci_get runtime || echo auto)"
image="$(uci_get image || echo ghcr.io/lyrion/lyrion:latest)"
image="$(uci_get image || echo ghcr.io/lms-community/lyrionmusicserver:stable)"
data_path="$(uci_get data_path || echo /srv/lyrion)"
media_path="$(uci_get media_path || echo /srv/media)"
port="$(uci_get port || echo 9000)"