diff --git a/package/secubox/secubox-app-crowdsec-bouncer/Makefile b/package/secubox/secubox-app-crowdsec-bouncer/Makefile new file mode 100644 index 00000000..3a1c6ecd --- /dev/null +++ b/package/secubox/secubox-app-crowdsec-bouncer/Makefile @@ -0,0 +1,43 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=secubox-app-crowdsec-bouncer +PKG_VERSION:=0.0.31 +PKG_RELEASE:=1 +PKG_ARCH:=all +PKG_MAINTAINER:=CyberMind Studio +PKG_LICENSE:=MIT + +include $(INCLUDE_DIR)/package.mk + +define Package/secubox-app-crowdsec-bouncer + SECTION:=net + CATEGORY:=Network + PKGARCH:=all + SUBMENU:=SecuBox Apps + TITLE:=SecuBox CrowdSec Firewall Bouncer wrapper + DEPENDS:=+uci +libuci +crowdsec-firewall-bouncer +crowdsec +nftables +endef + +define Package/secubox-app-crowdsec-bouncer/description +Enhanced wrapper for CrowdSec Firewall Bouncer with automatic configuration +and registration for SecuBox-powered OpenWrt routers. Provides nftables-based +IP blocking from CrowdSec decisions with automatic API key management and +interface detection. +endef + +define Package/secubox-app-crowdsec-bouncer/conffiles +/etc/config/crowdsec +endef + +define Build/Compile +endef + +define Package/secubox-app-crowdsec-bouncer/install + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_CONF) ./files/crowdsec-bouncer.config $(1)/etc/config/crowdsec-bouncer + + $(INSTALL_DIR) $(1)/etc/uci-defaults + $(INSTALL_BIN) ./files/crowdsec-bouncer.defaults $(1)/etc/uci-defaults/99_crowdsec-bouncer +endef + +$(eval $(call BuildPackage,secubox-app-crowdsec-bouncer)) diff --git a/package/secubox/secubox-app-crowdsec-bouncer/README.md b/package/secubox/secubox-app-crowdsec-bouncer/README.md new file mode 100644 index 00000000..b2995c06 --- /dev/null +++ b/package/secubox/secubox-app-crowdsec-bouncer/README.md @@ -0,0 +1,369 @@ +# SecuBox CrowdSec Firewall Bouncer + +Enhanced wrapper package for CrowdSec Firewall Bouncer with automatic configuration and registration for SecuBox-powered OpenWrt routers. + +## Overview + +The CrowdSec Firewall Bouncer is a component that blocks malicious IP addresses detected by CrowdSec using nftables firewall rules. This package wraps the upstream `crowdsec-firewall-bouncer` with SecuBox-specific enhancements: + +- **Automatic API key registration** with CrowdSec LAPI +- **Interface auto-detection** for LAN/WAN +- **Pre-configured defaults** optimized for routers +- **UCI configuration** for easy management via LuCI +- **Seamless integration** with SecuBox CrowdSec dashboard + +## Features + +- **nftables-based blocking**: Uses modern nftables instead of legacy iptables +- **IPv4 and IPv6 support**: Blocks threats on both protocol versions +- **Real-time updates**: Polls CrowdSec LAPI for new decisions (default: 10s) +- **Flexible filtering**: Configure INPUT and FORWARD chain filtering +- **Logging support**: Optional logging of blocked connections +- **Multiple deny actions**: drop, reject, or tarpit malicious traffic +- **Interface-based filtering**: Specify which interfaces to protect + +## Requirements + +- `crowdsec` - CrowdSec detection engine (must be installed and running) +- `crowdsec-firewall-bouncer` - Upstream firewall bouncer binary +- `nftables` - Modern Linux firewall +- Working CrowdSec Local API (LAPI) on port 8080 + +## Installation + +### Via opkg + +```bash +opkg update +opkg install secubox-app-crowdsec-bouncer +``` + +### From Source + +```bash +./secubox-tools/local-build.sh build secubox-app-crowdsec-bouncer +opkg install /path/to/secubox-app-crowdsec-bouncer_*.ipk +``` + +## Initial Configuration + +The package automatically configures itself on first install via the UCI defaults script: + +1. **Merges configuration** into `/etc/config/crowdsec` +2. **Detects network interfaces** (LAN/WAN) +3. **Registers bouncer** with CrowdSec LAPI +4. **Generates API key** and stores in UCI +5. **Loads nftables modules** + +After installation, you need to: + +```bash +# Enable the bouncer +uci set crowdsec.bouncer.enabled='1' +uci commit crowdsec + +# Start the service +/etc/init.d/crowdsec-firewall-bouncer enable +/etc/init.d/crowdsec-firewall-bouncer start +``` + +## Configuration + +All configuration is done via UCI at `/etc/config/crowdsec` in the `bouncer` section: + +```uci +config bouncer + option enabled '1' # Enable/disable bouncer + option ipv4 '1' # Enable IPv4 filtering + option ipv6 '1' # Enable IPv6 filtering + option api_url 'http://127.0.0.1:8080/' # CrowdSec LAPI URL + option api_key '' # API key (auto-generated) + option update_frequency '10s' # How often to poll for decisions + option priority '4' # nftables hook priority + option deny_action 'drop' # Action: drop|reject|tarpit + option deny_log '1' # Log blocked connections + option log_prefix 'CrowdSec: ' # Kernel log prefix + option log_level 'info' # Log level + option filter_input '1' # Filter INPUT chain + option filter_forward '1' # Filter FORWARD chain + option chain_name 'crowdsec-chain' # IPv4 chain name + option chain6_name 'crowdsec6-chain' # IPv6 chain name + option retry_initial_connect '1' # Retry if LAPI unavailable + list interface 'br-lan' # Interfaces to filter + list interface 'eth1' +``` + +### Common Configuration Tasks + +#### Change Update Frequency + +```bash +uci set crowdsec.bouncer.update_frequency='30s' +uci commit crowdsec +/etc/init.d/crowdsec-firewall-bouncer restart +``` + +#### Add/Remove Protected Interfaces + +```bash +# Add interface +uci add_list crowdsec.bouncer.interface='wlan0' + +# Remove specific interface +uci del_list crowdsec.bouncer.interface='eth1' + +# Commit and restart +uci commit crowdsec +/etc/init.d/crowdsec-firewall-bouncer restart +``` + +#### Change Deny Action + +```bash +# Options: drop (silent), reject (send ICMP), tarpit (slow response) +uci set crowdsec.bouncer.deny_action='reject' +uci commit crowdsec +/etc/init.d/crowdsec-firewall-bouncer restart +``` + +#### Enable/Disable Logging + +```bash +uci set crowdsec.bouncer.deny_log='1' # Enable +uci set crowdsec.bouncer.deny_log='0' # Disable +uci commit crowdsec +/etc/init.d/crowdsec-firewall-bouncer restart +``` + +## Manual Bouncer Registration + +If automatic registration fails, register manually: + +```bash +# Register bouncer and get API key +API_KEY=$(cscli bouncers add crowdsec-firewall-bouncer -o raw) + +# Set in UCI +uci set crowdsec.bouncer.api_key="$API_KEY" +uci commit crowdsec + +# Restart bouncer +/etc/init.d/crowdsec-firewall-bouncer restart +``` + +## Verification + +### Check Bouncer Status + +```bash +# Service status +/etc/init.d/crowdsec-firewall-bouncer status + +# Check if running +ps | grep cs-firewall-bouncer + +# Check bouncer registration +cscli bouncers list +``` + +### Check nftables Rules + +```bash +# IPv4 table +nft list table ip crowdsec + +# IPv6 table +nft list table ip6 crowdsec6 + +# Check blacklist set +nft list set ip crowdsec crowdsec-blacklists +``` + +### Verify Blocking + +```bash +# Add a test decision +cscli decisions add --ip 1.2.3.4 --duration 4h --reason "Test block" + +# Check if IP is in blacklist +nft list set ip crowdsec crowdsec-blacklists | grep 1.2.3.4 + +# Delete test decision +cscli decisions delete --ip 1.2.3.4 +``` + +### Check Logs + +```bash +# Service logs +logread | grep crowdsec-firewall-bouncer + +# Kernel logs for blocked packets (if deny_log=1) +dmesg | grep CrowdSec + +# Check bouncer log file +tail -f /var/log/crowdsec-firewall-bouncer.log +``` + +## How It Works + +1. **Startup**: + - Reads UCI configuration from `/etc/config/crowdsec` + - Generates YAML config at `/var/etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml` + - Creates nftables tables (`crowdsec`, `crowdsec6`) + - Creates nftables sets for blacklists + - Adds filter chains to INPUT/FORWARD hooks + +2. **Runtime**: + - Polls CrowdSec LAPI every `update_frequency` seconds + - Fetches active ban decisions + - Updates nftables sets with banned IPs + - Sets timeout based on decision duration + - Automatically removes expired bans + +3. **Shutdown**: + - Deletes nftables tables and chains + - Removes YAML config + - Cleans up resources + +## Integration with CrowdSec Dashboard + +The SecuBox CrowdSec dashboard (`luci-app-crowdsec-dashboard`) automatically detects the bouncer: + +- **Detection**: Checks for `cs-firewall-bouncer` process +- **Display**: Shows bouncer status in Overview page +- **Decisions**: Shows blocked IPs and applies them via bouncer + +Access the dashboard at: **System → CrowdSec → Overview** + +## Troubleshooting + +### Bouncer Not Starting + +**Check CrowdSec is running**: +```bash +/etc/init.d/crowdsec status +cscli lapi status +``` + +**Check nftables is available**: +```bash +nft list tables +modprobe nf_tables +``` + +**Check API key is set**: +```bash +uci get crowdsec.bouncer.api_key +``` + +### No IPs Being Blocked + +**Check for active decisions**: +```bash +cscli decisions list +``` + +**Check nftables sets**: +```bash +nft list set ip crowdsec crowdsec-blacklists +``` + +**Check bouncer can reach LAPI**: +```bash +# From bouncer log +logread | grep "connection refused\|timeout" +``` + +### Interface Not Filtered + +**Check interface list**: +```bash +uci show crowdsec.bouncer.interface +``` + +**Verify interface exists**: +```bash +ip link show +``` + +**Check nftables rules reference correct interface**: +```bash +nft list chain ip crowdsec crowdsec-chain-input +``` + +### High CPU Usage + +**Reduce update frequency**: +```bash +uci set crowdsec.bouncer.update_frequency='30s' +uci commit crowdsec +/etc/init.d/crowdsec-firewall-bouncer restart +``` + +**Disable logging**: +```bash +uci set crowdsec.bouncer.deny_log='0' +uci commit crowdsec +/etc/init.d/crowdsec-firewall-bouncer restart +``` + +## Advanced Configuration + +### Using Remote LAPI + +To connect to a remote CrowdSec LAPI: + +```bash +# Set remote LAPI URL +uci set crowdsec.bouncer.api_url='https://crowdsec-lapi.example.com:8080/' + +# Register bouncer on remote server +ssh remote-server "cscli bouncers add router-bouncer" + +# Copy API key and set locally +uci set crowdsec.bouncer.api_key='' +uci commit crowdsec +/etc/init.d/crowdsec-firewall-bouncer restart +``` + +### Custom Chain Priority + +Higher priority = earlier in filter chain: + +```bash +# Default is 4 (before normal filter rules) +uci set crowdsec.bouncer.priority='10' +uci commit crowdsec +/etc/init.d/crowdsec-firewall-bouncer restart +``` + +### Prometheus Metrics + +The bouncer can expose Prometheus metrics (requires recompilation with metrics enabled). + +## Files + +- `/etc/config/crowdsec` - UCI configuration +- `/etc/init.d/crowdsec-firewall-bouncer` - Init script (from upstream) +- `/var/etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml` - Generated YAML config +- `/var/log/crowdsec-firewall-bouncer.log` - Bouncer log file +- `/usr/bin/cs-firewall-bouncer` - Bouncer binary + +## Links + +- [CrowdSec Documentation](https://docs.crowdsec.net/) +- [Firewall Bouncer GitHub](https://github.com/crowdsecurity/cs-firewall-bouncer) +- [nftables Documentation](https://wiki.nftables.org/) +- [SecuBox Project](https://secubox.com) + +## License + +MIT License - See upstream package for details + +## Support + +For issues related to: +- **SecuBox integration**: Open issue on SecuBox GitHub +- **Bouncer functionality**: Refer to [cs-firewall-bouncer issues](https://github.com/crowdsecurity/cs-firewall-bouncer/issues) +- **CrowdSec core**: Refer to [CrowdSec documentation](https://docs.crowdsec.net/) diff --git a/package/secubox/secubox-app-crowdsec-bouncer/files/crowdsec-bouncer.config b/package/secubox/secubox-app-crowdsec-bouncer/files/crowdsec-bouncer.config new file mode 100644 index 00000000..ef40ad0f --- /dev/null +++ b/package/secubox/secubox-app-crowdsec-bouncer/files/crowdsec-bouncer.config @@ -0,0 +1,22 @@ +config bouncer + option enabled '0' + option ipv4 '1' + option ipv6 '1' + option api_url 'http://127.0.0.1:8080/' + option api_key '' + option update_frequency '10s' + option priority '4' + option deny_action 'drop' + option deny_log '1' + option log_prefix 'CrowdSec: ' + option log_level 'info' + option log_max_size '100' + option log_max_backups '3' + option log_max_age '30' + option filter_input '1' + option filter_forward '1' + option chain_name 'crowdsec-chain' + option chain6_name 'crowdsec6-chain' + option retry_initial_connect '1' + list interface 'br-lan' + list interface 'eth1' diff --git a/package/secubox/secubox-app-crowdsec-bouncer/files/crowdsec-bouncer.defaults b/package/secubox/secubox-app-crowdsec-bouncer/files/crowdsec-bouncer.defaults new file mode 100644 index 00000000..c42f4a2c --- /dev/null +++ b/package/secubox/secubox-app-crowdsec-bouncer/files/crowdsec-bouncer.defaults @@ -0,0 +1,154 @@ +#!/bin/sh +# +# CrowdSec Firewall Bouncer - UCI Defaults Script +# Automatically configures and registers the firewall bouncer on first install +# + +BOUNCER_NAME="crowdsec-firewall-bouncer" +CONFIG_FILE="/etc/config/crowdsec" +BOUNCER_CONFIG="/etc/config/crowdsec-bouncer" + +# Function to check if CrowdSec is installed and running +check_crowdsec() { + if ! command -v cscli >/dev/null 2>&1; then + echo "CrowdSec (cscli) not found. Please install crowdsec first." + return 1 + fi + + # Check if LAPI is reachable + if ! cscli lapi status >/dev/null 2>&1; then + echo "CrowdSec LAPI not running. Start crowdsec service first." + return 1 + fi + + return 0 +} + +# Function to register bouncer and get API key +register_bouncer() { + local api_key + + # Check if bouncer already registered + if cscli bouncers list | grep -q "$BOUNCER_NAME"; then + echo "Bouncer '$BOUNCER_NAME' already registered" + # Try to get existing key (note: cscli doesn't show keys after creation) + return 0 + fi + + # Register new bouncer + echo "Registering bouncer '$BOUNCER_NAME' with CrowdSec LAPI..." + api_key=$(cscli bouncers add "$BOUNCER_NAME" -o raw 2>/dev/null) + + if [ -n "$api_key" ] && [ "$api_key" != "null" ]; then + echo "Bouncer registered successfully" + # Update UCI config with API key + uci set crowdsec.bouncer.api_key="$api_key" + uci commit crowdsec + return 0 + else + echo "Failed to register bouncer" + return 1 + fi +} + +# Function to detect network interfaces +detect_interfaces() { + local interfaces="" + local lan_iface + local wan_iface + + # Get LAN interface + lan_iface=$(uci -q get network.lan.device) + [ -z "$lan_iface" ] && lan_iface=$(uci -q get network.lan.ifname) + [ -z "$lan_iface" ] && lan_iface="br-lan" + + # Get WAN interface + wan_iface=$(uci -q get network.wan.device) + [ -z "$wan_iface" ] && wan_iface=$(uci -q get network.wan.ifname) + [ -z "$wan_iface" ] && wan_iface="eth1" + + interfaces="$lan_iface $wan_iface" + + echo "$interfaces" +} + +# Function to merge bouncer config into main crowdsec config +merge_config() { + # Check if bouncer section already exists in main config + if ! uci -q get crowdsec.bouncer >/dev/null 2>&1; then + echo "Creating bouncer section in /etc/config/crowdsec..." + + # Copy from template if it exists + if [ -f "$BOUNCER_CONFIG" ]; then + # Read values from bouncer config template + uci -q import crowdsec < "$BOUNCER_CONFIG" + else + # Create basic bouncer section + uci set crowdsec.bouncer=bouncer + uci set crowdsec.bouncer.enabled='0' + uci set crowdsec.bouncer.ipv4='1' + uci set crowdsec.bouncer.ipv6='1' + uci set crowdsec.bouncer.api_url='http://127.0.0.1:8080/' + uci set crowdsec.bouncer.update_frequency='10s' + uci set crowdsec.bouncer.deny_action='drop' + uci set crowdsec.bouncer.deny_log='1' + uci set crowdsec.bouncer.log_prefix='CrowdSec: ' + uci set crowdsec.bouncer.log_level='info' + uci set crowdsec.bouncer.filter_input='1' + uci set crowdsec.bouncer.filter_forward='1' + fi + + # Auto-detect and set interfaces + local ifaces + ifaces=$(detect_interfaces) + uci delete crowdsec.bouncer.interface 2>/dev/null + for iface in $ifaces; do + uci add_list crowdsec.bouncer.interface="$iface" + done + + uci commit crowdsec + fi +} + +# Function to load nftables kernel modules +load_nftables_modules() { + modprobe nf_tables 2>/dev/null + modprobe nft_chain_nat 2>/dev/null + modprobe nf_nat 2>/dev/null +} + +# Main execution +main() { + echo "Configuring CrowdSec Firewall Bouncer..." + + # Merge configuration + merge_config + + # Load required kernel modules + load_nftables_modules + + # Check if CrowdSec is available + if ! check_crowdsec; then + echo "CrowdSec not ready. Bouncer registration skipped." + echo "Run 'cscli bouncers add $BOUNCER_NAME' manually after starting crowdsec." + exit 0 + fi + + # Register bouncer + if register_bouncer; then + echo "Bouncer configuration complete" + echo "Enable the bouncer with: uci set crowdsec.bouncer.enabled='1'; uci commit crowdsec" + echo "Start the service with: /etc/init.d/crowdsec-firewall-bouncer enable && /etc/init.d/crowdsec-firewall-bouncer start" + else + echo "Bouncer registration failed. You may need to register manually:" + echo " cscli bouncers add $BOUNCER_NAME" + fi +} + +# Run main function +main + +# Cleanup: remove this script after execution +rm -f /etc/uci-defaults/99_crowdsec-bouncer + +exit 0