A CrowdSec Bouncer for Unifi appliance
Warning
MongoDB CPU Overload Issue: Some users experience high CPU usage and slow UniFi control plane performance when running this bouncer due to excessive audit logging. See the MongoDB CPU Overload troubleshooting section for details and the workaround solution.
This repository aim to implement a CrowdSec bouncer for the routers of Unifi to block malicious IP to access your services. For this it leverages Unifi API to populate a dynamic Firewall Address List. Specically the Go Library go-unifi is used.
This is a Fork of funkolab/cs-mikrotik-bouncer and would not have been possible without this previous work
- Dream Machine Pro (UDM-Pro)
- Dream Machine SE (UDM-SE)
- Dream Machine Pro Max (UDM-Pro-Max)
- Gateway Lite (UXG-Lite)
- Gateway Pro (UXG-Pro)
- Gateway Enterprise (UXG-Enterprise)
- Cloud Gateway Max (UCG-Max)
- Cloud Gateway Ultra (UCG-Ultra)
- Cloud Gateway Fiber (UCG-Fiber)
- UniFi Express (UX)
- Dream Wall (DW)
- Enterprise Fortress Gateway (EFG)
For now, this web service is mainly thought to be used as a container.
If you need to build from source, you can get some inspiration from the Dockerfile.
You should have a Unifi appliance and a CrowdSec instance running.
The container is available as docker image ghcr.io/teifun2/cs-unifi-bouncer. It must have access to CrowdSec and to Unifi.
Generate a bouncer API key following CrowdSec documentation
- Get a bouncer API key from your CrowdSec with command
cscli bouncers add unifi-bouncer - Copy the API key printed. You WON'T be able the get it again.
- Paste this API key as the value for bouncer environment variable
CROWDSEC_BOUNCER_API_KEY, instead of "MyApiKey" - Start bouncer with
docker-compose up bouncerin theexampledirectory - It will directly communicate with your Unifi appliance and configure Rules and IP Groups
The bouncer configuration is made via environment variables:
| Name | Description | Default | Required |
|---|---|---|---|
CROWDSEC_BOUNCER_API_KEY |
CrowdSec bouncer API key required to be authorized to request local API | none |
✅ |
CROWDSEC_URL |
Host and port of CrowdSec agent | http://crowdsec:8080/ |
✅ |
CROWDSEC_ORIGINS |
Space separated list of CrowdSec origins to filter from LAPI (EG: "crowdsec cscli") | none |
❌ |
CROWDSEC_UPDATE_INTERVAL |
Interval Frequency Querying the Crowdsec API for changes to the blocklist. | 5s |
❌ |
CROWDSEC_SKIP_TLS_VERIFY |
Skips Certificate check for CrowdSec LAPI without proper SSL Certificate | false |
❌ |
LOG_LEVEL |
Minimum log level for bouncer (trace, debug, info, warn, error, fatal, panic) |
info |
❌ |
UNIFI_HOST |
Unifi appliance address | none |
✅ |
UNIFI_API_KEY |
Unifi appliance API key | none |
✅ / ❌ |
UNIFI_USER |
Unifi appliance username | none |
✅ / ❌ |
UNIFI_PASS |
Unifi appliance password | none |
✅ / ❌ |
UNIFI_IPV6 |
Enable / Disable IPv6 support | true |
❌ |
UNIFI_SITE |
Unifi Site Configuration in case of multiple sites | default |
❌ |
UNIFI_MAX_GROUP_SIZE |
UDM has a max IP Group size of 10'000 This might be different for other appliances | 10000 |
❌ |
UNIFI_IPV4_START_RULE_INDEX |
If you have other custom Rules defined in your Firewall this might need to be changed to prevent collisions (NOT FOR ZONE BASED FIREWALL) | 22000 |
❌ |
UNIFI_IPV6_START_RULE_INDEX |
If you have other custom Rules defined in your Firewall this might need to be changed to prevent collisions (NOT FOR ZONE BASED FIREWALL) | 27000 |
❌ |
UNIFI_SKIP_TLS_VERIFY |
Skips Certificate check for unifi controllers without proper SSL Certificate | false |
❌ |
UNIFI_LOGGING |
Generate Syslog entries when the firewall rules are matched | false |
❌ |
UNIFI_ZONE_SRC |
Space separated list of Source Zones for Firewall Policy in Zone Based mode | External |
❌ |
UNIFI_ZONE_DST |
Space separated list of Destination Zones for Firewall Policy in Zone Based mode | Internal Vpn Hotspot |
❌ |
UNIFI_POLICY_REORDERING |
Enable automatic reordering of firewall policies to ensure cs-unifi-bouncer policies have highest priority (before custom and default policies) | false |
❌ |
UNIFI_LOG_CLEANUP |
Enable automatic cleanup of MongoDB audit log entries to prevent CPU overload (see Troubleshooting) | false |
❌ |
UNIFI_LOG_CLEANUP_USER |
SSH username for audit log cleanup (usually root for UDM devices) |
root |
❌ |
UNIFI_LOG_CLEANUP_PASSWORD |
SSH password for audit log cleanup | none |
✅ if cleanup enabled |
UNIFI_LOG_CLEANUP_MINUTES |
How often (in minutes) the audit log cleanup runs and how far back (in minutes) it removes audit log entries | 30 |
❌ |
ENABLE_METRICS |
Enable tracking and reporting of dropped requests metrics to CrowdSec using UniFi traffic flows. | false |
❌ |
CROWDSEC_METRICS_MINUTES |
How often (in minutes) to poll UniFi for new traffic flows and send metrics back to CrowdSec. | 15 |
❌ |
Some users have reported that the UniFi control plane becomes slow or unresponsive after running the bouncer for a while. This is caused by the UniFi controller logging every individual IP address change to the admin_activity_log collection in MongoDB, which can grow very large (1GB+) and cause high CPU usage (300%+).
Symptoms:
- UniFi console becomes slow or unresponsive
- Console shows "Getting ready" for extended periods
mongodprocess at 300%+ CPU usage- Network continues to work, but control plane is unusable
Solution A: One-time MongoDB collection capping (no SSH credentials required)
This fix caps the admin_activity_log collection to 10 MB. Once applied, MongoDB automatically discards older entries to stay within the limit, preventing the collection from growing out of control. No bouncer configuration changes are needed.
SSH into your UniFi device and run:
# Drop the collection so it can be recreated as a capped collection
mongo ace --port 27117 --quiet --eval 'db.admin_activity_log.drop()'
# Cap the collection to 10 MB
mongo ace --port 27117 --quiet --eval 'db.runCommand({ convertToCapped: "admin_activity_log", size: 10000000 })'Note: The
dropcommand is optional —convertToCappedworks on an existing collection too and is sufficient on its own if you prefer not to lose existing log entries.
⚠️ Important: UniFi firmware/software updates may recreate theadmin_activity_logcollection without the capped configuration, causing the issue to reappear. If you notice the slowdown returning after an update, re-run theconvertToCappedcommand above. If you prefer a fully automated fix that survives updates, use Solution B instead.
Solution B: Automatic periodic cleanup via SSH (bouncer-managed)
Enable the audit log cleanup feature by setting these environment variables:
environment:
UNIFI_LOG_CLEANUP: "true"
UNIFI_LOG_CLEANUP_USER: "root"
UNIFI_LOG_CLEANUP_PASSWORD: "your-ssh-password"This feature connects via SSH to your UniFi device periodically (based on UNIFI_LOG_CLEANUP_MINUTES) and cleans up the verbose audit log entries, replacing thousands of individual IP entries with a simple "Updated from bouncer" message. This preserves the audit trail while eliminating the performance impact.
This feature requires enabling SSH access on your UniFi device and storing the SSH password in your configuration. Please be aware:
- This is a workaround for a problem caused by UniFi's excessive audit logging, not our intended method of operation
- Enabling SSH and storing credentials increases your security risk
- SSH uses
InsecureIgnoreHostKeyfor host key verification (accepts any host key) - Only enable this feature if you are experiencing the MongoDB CPU overload issue
- Use this at your own risk and ensure your network is properly secured
- Consider using strong passwords and restricting SSH access to specific IP addresses if possible
Note: You need to enable SSH access on your UniFi device and know the root password. The SSH password is typically the same as your device's management password.
Any constructive feedback is welcome, feel free to add an issue or a pull request. I will review it and integrate it to the code.
