developingchet/cs-unifi-bouncer-pro

By developingchet

Updated 4 months ago

Production-grade CrowdSec bouncer for UniFi network controllers

Image
Networking
Security
Monitoring & observability
0

5.0K

developingchet/cs-unifi-bouncer-pro repository overview

CrowdSec Unifi Bouncer Logo

cs-unifi-bouncer-pro

Build Version License: MIT Docker Pulls


Summary

cs-unifi-bouncer-pro is a production-grade CrowdSec bouncer for self-hosted UniFi network controllers. It automatically translates CrowdSec ban decisions into firewall rules, blocking malicious IPs at the network edge in real time.

It auto-detects zone-based (UniFi Network ≥ 8.x) or legacy WAN_IN firewall modes, applies bans across multiple sites simultaneously, and manages multi-shard Traffic Matching Lists with bin-packing and automatic rebalance. Bans are persisted in a crash-safe bbolt database, a configurable circuit breaker handles controller outages, and startup reconciliation corrects drift after a crash or restart. The image is distroless, under 20 MB, runs as nonroot (UID 65532), and is Cosign-signed with a CycloneDX SBOM attached to every release.


Quick Start

services:
  bouncer:
    image: developingchet/cs-unifi-bouncer-pro:latest
    restart: unless-stopped
    environment:
      UNIFI_URL: https://192.168.1.1
      UNIFI_API_KEY: your-api-key
      CROWDSEC_LAPI_URL: http://crowdsec:8080
      CROWDSEC_LAPI_KEY: your-bouncer-key
      ZONE_PAIRS: External->Dmz
    volumes:
      - bouncer-data:/data
volumes:
  bouncer-data:

For full setup including CrowdSec registration, TLS, multi-site, and Docker Secrets support, see the Setup Guide.


Features

  • Dual firewall modes — auto-detects zone-based (UniFi ≥ 8.x) or legacy WAN_IN; no manual config required
  • Multi-site — bans applied to all configured UniFi sites simultaneously from a single instance
  • Batch sync with bin-packing — fills shards before creating new ones; dirty shards flushed immediately after each decision batch
  • Shard rebalance — collapses under-filled TMLs automatically after expiry (SHARD_MERGE_THRESHOLD)
  • Circuit breaker — configurable failure threshold and cooldown; suspends syncs when the controller is unhealthy
  • Crash-safe bbolt persistence — bbolt-first write ordering; startup reconcile corrects drift after a crash or restart
  • 20 Prometheus metrics — decisions, API calls, active bans, shard occupancy, decision latency, circuit breaker state
  • Decision latency histogram — end-to-end timing from CrowdSec filter pipeline to successful UniFi write
  • CrowdSec usage-metrics — decision telemetry pushed to LAPI /v1/usage-metrics (default: 30 min; configurable)
  • Cloudflare whitelist sync — ALLOW policies for Cloudflare IP ranges, auto-refreshed on a configurable schedule
  • Ban history audit trail — ring-buffer event log (up to 10,000 entries) for every ban, unban, and expiry; queryable via status bans, status ip, status history
  • External blocklist import — fetch plain-text IP/CIDR lists from external URLs on a configurable interval; bans auto-expire if the feed goes offline
  • Webhook notifications — POST JSON alerts when the circuit breaker trips or reconcile drift is detected
  • Per-scenario duration overrides — override BAN_TTL per CrowdSec scenario via BLOCK_SCENARIO_DURATION_MAP
  • Per-scenario zone routing — route bans from specific scenarios to different zone pairs via ZONE_PAIRS_SCENARIO_MAP
  • Destination IP filtering — scope block policies to specific destination hosts or subnets via @ip1,ip2,... suffix on zone pairs
  • Decision rate limiter — token-bucket throttle for ban waves (DECISION_RATE_LIMIT)
  • Validate and diagnose subcommands — CI-safe config validation; three-phase connectivity check with zone discovery
  • Log redaction — RedactWriter masks passwords, API keys, and Bearer tokens before they reach stdout
  • Dry-run mode — connects and reads live state; logs all intended changes without writing anything to UniFi
  • Multi-arch distroless image — amd64, arm64, armv7; under 20 MB; runs as nonroot (UID 65532)
  • Cosign-signed + CycloneDX SBOM — keyless OIDC image signing and SBOM attestation on every release

Required Configuration

VariableExampleDescription
UNIFI_URLhttps://192.168.1.1UniFi controller base URL
UNIFI_API_KEYyour-api-keyAPI key (Settings → Control Plane → API Keys); or use UNIFI_USERNAME + UNIFI_PASSWORD
CROWDSEC_LAPI_URLhttp://crowdsec:8080CrowdSec LAPI URL (default assumes a Docker service named crowdsec)
CROWDSEC_LAPI_KEYyour-bouncer-keyBouncer key from cscli bouncers add unifi-bouncer
ZONE_PAIRSExternal->DmzZone pair(s) for block policies; src[:sport,...]->dst[:dport,...][@dstIP,...] — port and destination IP filters are optional

Sensitive variables (UNIFI_API_KEY, UNIFI_PASSWORD, CROWDSEC_LAPI_KEY) accept a _FILE suffix for Docker secrets and Kubernetes secret mounts. For the full variable reference see the Configuration Reference.


Image Tags

TagWhen to use
lateststable, always points to the newest release
v1.2.5exact version, recommended for production
1.0minor-pinned
1major-pinned

Supply Chain

This image is signed with Cosign (keyless OIDC). Verify with:

cosign verify developingchet/cs-unifi-bouncer-pro:v1.2.5 \
  --certificate-identity-regexp="https://github.com/developingchet/cs-unifi-bouncer-pro/.github/workflows/release.yml@refs/tags/.*" \
  --certificate-oidc-issuer="https://token.actions.githubusercontent.com"

A CycloneDX SBOM is attached to each release and embedded as a Cosign attestation on the image.


Tag summary

Content type

Image

Digest

sha256:9373d66be

Size

423.2 kB

Last updated

4 months ago

docker pull developingchet/cs-unifi-bouncer-pro:sha256-6ba45fd33fe9147d9fc3101703b21c02dd74d1f3dd7dfc0af2f4f2ac3ea510e6.att