A filtering proxy for CrowdSec that sits between your local CrowdSec instances (LAPI) and the Central API (CAPI). Filter alerts before they're sent to the CrowdSec console, and visualize them in a local dashboard.
- Alert Filtering: Powerful expression-based filter rules with logical operators (and, or, not)
- Field operators: eq, ne, gt, lt, in, contains, starts_with, ends_with, regex, glob, cidr
- Combinable conditions for complex filtering logic
- Client Validation: Optional validation of CrowdSec clients against CAPI before accepting alerts
- Dashboard: Web interface to visualize alerts with GeoIP enrichment
- Transparent Proxy: Forwards non-filtered alerts to CAPI
- GeoIP Enrichment: Enrich alerts with geographic information
- Lightweight: Docker image under 250MB
# Clone the repository
git clone https://github.com/yourusername/crowdsieve.git
cd crowdsieve
# Start the services (proxy + dashboard)
docker compose up -d
# View logs
docker compose logs -fThe container runs both services:
- Proxy: http://localhost:8080 (for CrowdSec LAPI)
- Dashboard: http://localhost:3000 (web interface)
# Install dependencies
npm install
cd dashboard && npm install && cd ..
# Start in development mode (2 terminals)
npm run dev # Terminal 1: Proxy on :8080
npm run dev:dashboard # Terminal 2: Dashboard on :3000
# Build for production
npm run build
npm startOn each CrowdSec server that should use the proxy, update /etc/crowdsec/online_api_credentials.yaml:
# Before
url: https://api.crowdsec.net/
# After
url: http://YOUR_PROXY_IP:8080/Then restart CrowdSec:
sudo systemctl restart crowdsecEdit config/filters.yaml:
proxy:
listen_port: 8080
capi_url: 'https://api.crowdsec.net'
timeout_ms: 30000
forward_enabled: true # Set to false for test mode
storage:
path: './data/crowdsieve.db'
retention_days: 30
filters:
mode: 'block' # "block" = matching alerts NOT forwarded; "allow" = only matching forwarded
# Rules are loaded from config/filters.d/*.yamlFilter rules are YAML files in config/filters.d/. Each rule uses an expression-based syntax:
# config/filters.d/00-no-decision.yaml
name: no-decision
enabled: true
description: 'Block alerts without decisions'
filter:
field: decisions
op: empty# config/filters.d/10-internal-ips.yaml
name: internal-ips
enabled: true
description: 'Block internal IP ranges'
filter:
field: source.ip
op: cidr
value:
- '10.0.0.0/8'
- '172.16.0.0/12'
- '192.168.0.0/16'# Complex filter with logical operators
name: complex-filter
enabled: true
filter:
op: and
conditions:
- field: scenario
op: glob
value: 'crowdsecurity/*'
- op: not
condition:
field: source.country
op: in
value: ['FR', 'DE', 'US']| Operator | Description |
|---|---|
eq, ne |
Equals / Not equals |
gt, gte, lt, lte |
Numeric comparisons |
in, not_in |
Value in array |
contains, not_contains |
String/array contains |
starts_with, ends_with |
String prefix/suffix |
glob, regex |
Pattern matching |
cidr |
IP in CIDR range(s) |
empty, not_empty |
Check if empty |
and, or, not |
Logical operators |
CrowdSieve can optionally validate CrowdSec clients against CAPI before accepting alerts. This prevents unauthorized clients from sending data through the proxy.
Enable via environment variables:
CLIENT_VALIDATION_ENABLED=true
CLIENT_VALIDATION_CACHE_TTL=604800 # Cache valid clients for 1 week
CLIENT_VALIDATION_CACHE_TTL_ERROR=3600 # Cache on CAPI errors for 1 hour
CLIENT_VALIDATION_FAIL_CLOSED=false # Set to true to reject when CAPI unavailableValidation uses a dual-layer cache (in-memory LRU + SQLite) for performance.
| Variable | Default | Description |
|---|---|---|
CONFIG_PATH |
./config/filters.yaml |
Path to config file |
DATABASE_PATH |
./data/crowdsieve.db |
Path to SQLite database |
GEOIP_DB_PATH |
./data/GeoLite2-City.mmdb |
Path to GeoIP database |
PROXY_PORT |
8080 |
Proxy listen port |
DASHBOARD_PORT |
3000 |
Dashboard listen port |
LOG_LEVEL |
info |
Log level (debug, info, warn, error) |
LOG_FORMAT |
json |
Log format (json, pretty) |
FORWARD_ENABLED |
true |
Set to false to disable CAPI forwarding (test mode) |
CLIENT_VALIDATION_ENABLED |
false |
Enable client validation against CAPI |
CLIENT_VALIDATION_CACHE_TTL |
604800 |
Cache TTL for validated clients (seconds) |
CLIENT_VALIDATION_FAIL_CLOSED |
false |
Reject requests when CAPI is unavailable |
To enable GeoIP enrichment, download the MaxMind GeoLite2-City database:
- Create a free account at MaxMind
- Download
GeoLite2-City.mmdb - Place it in
./data/GeoLite2-City.mmdb
# Install dependencies
npm install
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Type checking
npm run typecheck
# Linting
npm run lintflowchart LR
subgraph Clients
LAPI1[CrowdSec LAPI]
LAPI2[CrowdSec LAPI]
LAPI3[CrowdSec LAPI]
end
subgraph CrowdSieve
Proxy[Fastify Proxy<br/>:8080]
DB[(SQLite DB)]
Dashboard[Next.js Dashboard<br/>:3000]
end
CAPI[CrowdSec CAPI<br/>api.crowdsec.net]
LAPI1 --> Proxy
LAPI2 --> Proxy
LAPI3 --> Proxy
Proxy --> CAPI
Proxy --> DB
Dashboard --> DB
AGPL-3.0-only