diff --git a/package/secubox/luci-app-crowdsec-dashboard/Makefile b/package/secubox/luci-app-crowdsec-dashboard/Makefile index d0d76f1a..a55cce8d 100644 --- a/package/secubox/luci-app-crowdsec-dashboard/Makefile +++ b/package/secubox/luci-app-crowdsec-dashboard/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-crowdsec-dashboard PKG_VERSION:=0.7.0 -PKG_RELEASE:=27 +PKG_RELEASE:=28 PKG_ARCH:=all PKG_LICENSE:=Apache-2.0 diff --git a/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/overview.js b/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/overview.js index c0403f4b..9a3eeb42 100644 --- a/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/overview.js +++ b/package/secubox/luci-app-crowdsec-dashboard/htdocs/luci-static/resources/view/crowdsec-dashboard/overview.js @@ -526,6 +526,7 @@ return view.extend({ ]), E('div', { 'class': 'cs-charts-row' }, [ + this.renderFirewallHealth(), this.renderFirewallBlocks() ]), @@ -871,6 +872,78 @@ return view.extend({ ]); }, + // Firewall Health Status Card + renderFirewallHealth: function() { + var stats = this.nftablesStats || {}; + var health = stats.firewall_health || {}; + + var status = health.status || 'unknown'; + var issues = health.issues || ''; + var bouncerRunning = health.bouncer_running; + var uciEnabled = health.uci_enabled; + var apiKeyConfigured = health.api_key_configured; + var inputHooked = health.input_chain_hooked; + var forwardHooked = health.forward_chain_hooked; + var setsHaveTimeout = health.sets_have_timeout; + var decisionsSynced = health.decisions_synced; + var cscliDecisions = health.cscli_decisions_count || 0; + var nftElements = health.nft_elements_count || 0; + + var statusColor = status === 'ok' ? '#00d4aa' : (status === 'warning' ? '#ffa500' : '#ff4757'); + var statusIcon = status === 'ok' ? '✅' : (status === 'warning' ? '⚠️' : '❌'); + var statusText = status === 'ok' ? 'Healthy' : (status === 'warning' ? 'Warning' : 'Error'); + + var checkItems = [ + { label: 'Bouncer Process', ok: bouncerRunning, detail: bouncerRunning ? 'Running' : 'Not running' }, + { label: 'UCI Enabled', ok: uciEnabled, detail: uciEnabled ? 'Enabled' : 'Disabled' }, + { label: 'API Key', ok: apiKeyConfigured, detail: apiKeyConfigured ? 'Configured' : 'Missing or default' }, + { label: 'Input Chain', ok: inputHooked, detail: inputHooked ? 'Hooked' : 'Not hooked' }, + { label: 'Forward Chain', ok: forwardHooked, detail: forwardHooked ? 'Hooked' : 'Not hooked' }, + { label: 'Set Timeout', ok: setsHaveTimeout, detail: setsHaveTimeout ? 'Enabled' : 'Disabled' }, + { label: 'Decisions Sync', ok: decisionsSynced, detail: decisionsSynced ? (nftElements + ' synced') : 'Out of sync' } + ]; + + var checkRows = checkItems.map(function(item) { + return E('div', { 'style': 'display: flex; align-items: center; justify-content: space-between; padding: 0.4em 0; border-bottom: 1px solid rgba(255,255,255,0.05);' }, [ + E('div', { 'style': 'display: flex; align-items: center; gap: 0.5em;' }, [ + E('span', { 'style': 'font-size: 1em;' }, item.ok ? '✅' : '❌'), + E('span', { 'style': 'font-size: 0.85em;' }, item.label) + ]), + E('span', { 'style': 'font-size: 0.75em; color: ' + (item.ok ? '#00d4aa' : '#ff4757') + ';' }, item.detail) + ]); + }); + + return E('div', { 'class': 'cs-card', 'style': 'flex: 1;' }, [ + E('div', { 'class': 'cs-card-header' }, [ + E('div', { 'class': 'cs-card-title' }, [ + _('Firewall Health'), + E('span', { + 'style': 'margin-left: 0.75em; font-size: 0.8em; padding: 0.2em 0.6em; background: ' + statusColor + '; border-radius: 12px;' + }, statusIcon + ' ' + statusText) + ]) + ]), + E('div', { 'class': 'cs-card-body' }, [ + // Status summary + issues ? E('div', { 'style': 'background: rgba(255,71,87,0.1); border: 1px solid rgba(255,71,87,0.3); border-radius: 8px; padding: 0.75em; margin-bottom: 1em;' }, [ + E('div', { 'style': 'font-size: 0.85em; color: #ff4757;' }, issues) + ]) : E('span'), + // Sync stats + E('div', { 'style': 'display: flex; gap: 1em; margin-bottom: 1em;' }, [ + E('div', { 'style': 'flex: 1; text-align: center; padding: 0.5em; background: rgba(102,126,234,0.1); border-radius: 8px;' }, [ + E('div', { 'style': 'font-size: 1.25em; font-weight: 700; color: #667eea;' }, String(cscliDecisions)), + E('div', { 'style': 'font-size: 0.7em; color: #888;' }, 'Decisions') + ]), + E('div', { 'style': 'flex: 1; text-align: center; padding: 0.5em; background: rgba(0,212,170,0.1); border-radius: 8px;' }, [ + E('div', { 'style': 'font-size: 1.25em; font-weight: 700; color: #00d4aa;' }, String(nftElements)), + E('div', { 'style': 'font-size: 0.7em; color: #888;' }, 'In Firewall') + ]) + ]), + // Check items + E('div', {}, checkRows) + ]) + ]); + }, + // Firewall Blocks - Shows IPs blocked in nftables renderFirewallBlocks: function() { var self = this; diff --git a/package/secubox/luci-app-crowdsec-dashboard/root/usr/libexec/rpcd/luci.crowdsec-dashboard b/package/secubox/luci-app-crowdsec-dashboard/root/usr/libexec/rpcd/luci.crowdsec-dashboard index 9e12d892..bafe0732 100755 --- a/package/secubox/luci-app-crowdsec-dashboard/root/usr/libexec/rpcd/luci.crowdsec-dashboard +++ b/package/secubox/luci-app-crowdsec-dashboard/root/usr/libexec/rpcd/luci.crowdsec-dashboard @@ -947,6 +947,86 @@ get_nftables_stats() { json_add_int "ipv6_cscli_count" "$ipv6_cscli" json_add_int "ipv6_total_count" "$((ipv6_capi + ipv6_cscli))" + # Firewall Health Check + json_add_object "firewall_health" + + # Check bouncer process + local bouncer_running=0 + if pgrep cs-firewall-bouncer >/dev/null 2>&1; then + bouncer_running=1 + fi + json_add_boolean "bouncer_running" "$bouncer_running" + + # Check UCI config + local uci_enabled=0 + local uci_api_key="" + if uci -q get crowdsec.bouncer.enabled >/dev/null 2>&1; then + [ "$(uci -q get crowdsec.bouncer.enabled)" = "1" ] && uci_enabled=1 + fi + uci_api_key=$(uci -q get crowdsec.bouncer.api_key 2>/dev/null) + json_add_boolean "uci_enabled" "$uci_enabled" + json_add_boolean "api_key_configured" "$([ -n "$uci_api_key" ] && [ "$uci_api_key" != "API_KEY" ] && echo 1 || echo 0)" + + # Check chains are hooked (input/forward) + local input_hooked=0 + local forward_hooked=0 + if [ "$ipv4_exists" = "1" ]; then + nft list table ip crowdsec 2>/dev/null | grep -q "hook input" && input_hooked=1 + nft list table ip crowdsec 2>/dev/null | grep -q "hook forward" && forward_hooked=1 + fi + json_add_boolean "input_chain_hooked" "$input_hooked" + json_add_boolean "forward_chain_hooked" "$forward_hooked" + + # Check if sets have timeout flag (required for auto-expiry) + local sets_have_timeout=0 + if [ "$ipv4_exists" = "1" ]; then + nft list set ip crowdsec crowdsec-blacklists 2>/dev/null | grep -q "flags timeout" && sets_have_timeout=1 + fi + json_add_boolean "sets_have_timeout" "$sets_have_timeout" + + # Check decisions sync (compare cscli decisions count vs nftables) + local cscli_decisions=0 + local nft_elements=0 + local sync_ok=0 + if command -v cscli >/dev/null 2>&1; then + cscli_decisions=$(cscli decisions list -o json 2>/dev/null | jsonfilter -e '@[*]' 2>/dev/null | wc -l || echo "0") + fi + nft_elements=$((ipv4_capi + ipv4_cscli + ipv4_other + ipv6_capi + ipv6_cscli)) + # Sync is OK if nft has at least some elements when decisions exist + [ "$cscli_decisions" -gt 0 ] && [ "$nft_elements" -gt 0 ] && sync_ok=1 + [ "$cscli_decisions" -eq 0 ] && [ "$nft_elements" -eq 0 ] && sync_ok=1 + json_add_int "cscli_decisions_count" "$cscli_decisions" + json_add_int "nft_elements_count" "$nft_elements" + json_add_boolean "decisions_synced" "$sync_ok" + + # Overall health status + local health_status="ok" + local health_issues="" + if [ "$bouncer_running" != "1" ]; then + health_status="error" + health_issues="Bouncer not running; " + fi + if [ "$uci_enabled" != "1" ]; then + health_status="warning" + health_issues="${health_issues}Bouncer not enabled in UCI; " + fi + if [ "$ipv4_exists" != "1" ]; then + health_status="error" + health_issues="${health_issues}IPv4 table missing; " + fi + if [ "$input_hooked" != "1" ] && [ "$forward_hooked" != "1" ]; then + health_status="error" + health_issues="${health_issues}No chains hooked; " + fi + if [ "$sync_ok" != "1" ]; then + health_status="warning" + health_issues="${health_issues}Decisions not synced to firewall; " + fi + json_add_string "status" "$health_status" + json_add_string "issues" "$health_issues" + + json_close_object + json_dump } diff --git a/package/secubox/luci-app-secubox-crowdsec/Makefile b/package/secubox/luci-app-secubox-crowdsec/Makefile index 96a61ea4..f6c707f8 100644 --- a/package/secubox/luci-app-secubox-crowdsec/Makefile +++ b/package/secubox/luci-app-secubox-crowdsec/Makefile @@ -11,7 +11,7 @@ PKG_VERSION:=1.0.0 PKG_RELEASE:=1 LUCI_TITLE:=LuCI SecuBox CrowdSec Dashboard -LUCI_DEPENDS:=+luci-base +crowdsec +crowdsec-firewall-bouncer +LUCI_DEPENDS:=+luci-base +crowdsec +secubox-app-cs-firewall-bouncer LUCI_PKGARCH:=all PKG_MAINTAINER:=Gerald Kerma diff --git a/package/secubox/secubox-auth-logger/Makefile b/package/secubox/secubox-app-auth-logger/Makefile similarity index 80% rename from package/secubox/secubox-auth-logger/Makefile rename to package/secubox/secubox-app-auth-logger/Makefile index b7d22794..c1f24bf5 100644 --- a/package/secubox/secubox-auth-logger/Makefile +++ b/package/secubox/secubox-app-auth-logger/Makefile @@ -3,7 +3,7 @@ include $(TOPDIR)/rules.mk -PKG_NAME:=secubox-auth-logger +PKG_NAME:=secubox-app-auth-logger PKG_VERSION:=1.2.2 PKG_RELEASE:=1 PKG_ARCH:=all @@ -12,15 +12,16 @@ PKG_MAINTAINER:=CyberMind include $(INCLUDE_DIR)/package.mk -define Package/secubox-auth-logger +define Package/secubox-app-auth-logger SECTION:=secubox CATEGORY:=SecuBox TITLE:=Authentication Failure Logger for CrowdSec DEPENDS:=+rpcd +uhttpd +libubox-lua PKGARCH:=all + PROVIDES:=secubox-auth-logger endef -define Package/secubox-auth-logger/description +define Package/secubox-app-auth-logger/description Logs authentication failures from LuCI/rpcd and Dropbear SSH for CrowdSec detection. Includes: - SSH failure monitoring (OpenSSH/Dropbear) @@ -32,14 +33,14 @@ endef define Build/Compile endef -define Package/secubox-auth-logger/install +define Package/secubox-app-auth-logger/install # Auth monitor script $(INSTALL_DIR) $(1)/usr/lib/secubox $(INSTALL_BIN) ./files/auth-monitor.sh $(1)/usr/lib/secubox/ # Init script $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_BIN) ./files/secubox-auth-logger.init $(1)/etc/init.d/secubox-auth-logger + $(INSTALL_BIN) ./files/secubox-app-auth-logger.init $(1)/etc/init.d/secubox-app-auth-logger # RPCD plugin for auth logging via ubus $(INSTALL_DIR) $(1)/usr/libexec/rpcd @@ -61,10 +62,6 @@ define Package/secubox-auth-logger/install $(INSTALL_DIR) $(1)/etc/crowdsec/parsers/s01-parse $(INSTALL_DATA) ./files/openwrt-luci-auth.yaml $(1)/etc/crowdsec/parsers/s01-parse/ - # CrowdSec whitelist for private IPs (RFC1918) - $(INSTALL_DIR) $(1)/etc/crowdsec/parsers/s02-enrich - $(INSTALL_DATA) ./files/secubox-private-ip-whitelist.yaml $(1)/etc/crowdsec/parsers/s02-enrich/ - # CrowdSec scenario $(INSTALL_DIR) $(1)/etc/crowdsec/scenarios $(INSTALL_DATA) ./files/openwrt-luci-bf.yaml $(1)/etc/crowdsec/scenarios/ @@ -75,28 +72,28 @@ define Package/secubox-auth-logger/install # UCI defaults for first boot setup $(INSTALL_DIR) $(1)/etc/uci-defaults - $(INSTALL_BIN) ./files/99-secubox-auth-logger $(1)/etc/uci-defaults/ + $(INSTALL_BIN) ./files/99-secubox-app-auth-logger $(1)/etc/uci-defaults/ endef -define Package/secubox-auth-logger/postinst +define Package/secubox-app-auth-logger/postinst #!/bin/sh [ -n "$${IPKG_INSTROOT}" ] || { # Restart rpcd to load new plugin /etc/init.d/rpcd restart 2>/dev/null # Enable and start auth monitor - /etc/init.d/secubox-auth-logger enable - /etc/init.d/secubox-auth-logger start + /etc/init.d/secubox-app-auth-logger enable + /etc/init.d/secubox-app-auth-logger start # Run uci-defaults to inject JS hook - /etc/uci-defaults/99-secubox-auth-logger 2>/dev/null || true + /etc/uci-defaults/99-secubox-app-auth-logger 2>/dev/null || true echo "SecuBox Auth Logger installed - LuCI login failures now logged for CrowdSec" } exit 0 endef -define Package/secubox-auth-logger/postrm +define Package/secubox-app-auth-logger/postrm #!/bin/sh [ -n "$${IPKG_INSTROOT}" ] || { # Restore dispatcher from backup @@ -127,4 +124,4 @@ define Package/secubox-auth-logger/postrm exit 0 endef -$(eval $(call BuildPackage,secubox-auth-logger)) +$(eval $(call BuildPackage,secubox-app-auth-logger)) diff --git a/package/secubox/secubox-auth-logger/files/99-secubox-auth-logger b/package/secubox/secubox-app-auth-logger/files/99-secubox-app-auth-logger similarity index 100% rename from package/secubox/secubox-auth-logger/files/99-secubox-auth-logger rename to package/secubox/secubox-app-auth-logger/files/99-secubox-app-auth-logger diff --git a/package/secubox/secubox-auth-logger/files/auth-hook.cgi b/package/secubox/secubox-app-auth-logger/files/auth-hook.cgi similarity index 100% rename from package/secubox/secubox-auth-logger/files/auth-hook.cgi rename to package/secubox/secubox-app-auth-logger/files/auth-hook.cgi diff --git a/package/secubox/secubox-auth-logger/files/auth-monitor.sh b/package/secubox/secubox-app-auth-logger/files/auth-monitor.sh similarity index 100% rename from package/secubox/secubox-auth-logger/files/auth-monitor.sh rename to package/secubox/secubox-app-auth-logger/files/auth-monitor.sh diff --git a/package/secubox/secubox-auth-logger/files/luci-secubox-auth.acl.json b/package/secubox/secubox-app-auth-logger/files/luci-secubox-auth.acl.json similarity index 100% rename from package/secubox/secubox-auth-logger/files/luci-secubox-auth.acl.json rename to package/secubox/secubox-app-auth-logger/files/luci-secubox-auth.acl.json diff --git a/package/secubox/secubox-auth-logger/files/openwrt-luci-auth.yaml b/package/secubox/secubox-app-auth-logger/files/openwrt-luci-auth.yaml similarity index 100% rename from package/secubox/secubox-auth-logger/files/openwrt-luci-auth.yaml rename to package/secubox/secubox-app-auth-logger/files/openwrt-luci-auth.yaml diff --git a/package/secubox/secubox-auth-logger/files/openwrt-luci-bf.yaml b/package/secubox/secubox-app-auth-logger/files/openwrt-luci-bf.yaml similarity index 100% rename from package/secubox/secubox-auth-logger/files/openwrt-luci-bf.yaml rename to package/secubox/secubox-app-auth-logger/files/openwrt-luci-bf.yaml diff --git a/package/secubox/secubox-auth-logger/files/secubox-auth-logger.init b/package/secubox/secubox-app-auth-logger/files/secubox-app-auth-logger.init similarity index 100% rename from package/secubox/secubox-auth-logger/files/secubox-auth-logger.init rename to package/secubox/secubox-app-auth-logger/files/secubox-app-auth-logger.init diff --git a/package/secubox/secubox-auth-logger/files/secubox-auth-acquis.yaml b/package/secubox/secubox-app-auth-logger/files/secubox-auth-acquis.yaml similarity index 100% rename from package/secubox/secubox-auth-logger/files/secubox-auth-acquis.yaml rename to package/secubox/secubox-app-auth-logger/files/secubox-auth-acquis.yaml diff --git a/package/secubox/secubox-auth-logger/files/secubox-auth-hook.js b/package/secubox/secubox-app-auth-logger/files/secubox-auth-hook.js similarity index 100% rename from package/secubox/secubox-auth-logger/files/secubox-auth-hook.js rename to package/secubox/secubox-app-auth-logger/files/secubox-auth-hook.js diff --git a/package/secubox/secubox-auth-logger/files/secubox.auth-logger b/package/secubox/secubox-app-auth-logger/files/secubox.auth-logger similarity index 100% rename from package/secubox/secubox-auth-logger/files/secubox.auth-logger rename to package/secubox/secubox-app-auth-logger/files/secubox.auth-logger diff --git a/package/secubox/secubox-app-crowdsec-bouncer/Makefile b/package/secubox/secubox-app-crowdsec-bouncer/Makefile index f2023a8f..cbb5dc71 100644 --- a/package/secubox/secubox-app-crowdsec-bouncer/Makefile +++ b/package/secubox/secubox-app-crowdsec-bouncer/Makefile @@ -15,7 +15,7 @@ define Package/secubox-app-crowdsec-bouncer PKGARCH:=all SUBMENU:=SecuBox Apps TITLE:=SecuBox CrowdSec Firewall Bouncer wrapper - DEPENDS:=+uci +libuci +crowdsec-firewall-bouncer +crowdsec +nftables + DEPENDS:=+uci +libuci +secubox-app-cs-firewall-bouncer +crowdsec +nftables endef define Package/secubox-app-crowdsec-bouncer/description diff --git a/package/secubox/crowdsec-firewall-bouncer/Makefile b/package/secubox/secubox-app-cs-firewall-bouncer/Makefile similarity index 58% rename from package/secubox/crowdsec-firewall-bouncer/Makefile rename to package/secubox/secubox-app-cs-firewall-bouncer/Makefile index ca0a36ff..6b961fd7 100644 --- a/package/secubox/crowdsec-firewall-bouncer/Makefile +++ b/package/secubox/secubox-app-cs-firewall-bouncer/Makefile @@ -3,18 +3,20 @@ # Copyright (C) 2021-2022 Gerald Kerma # Copyright (C) 2024-2025 CyberMind.fr (SecuBox adaptation) # -# CrowdSec Firewall Bouncer - nftables integration +# SecuBox CrowdSec Firewall Bouncer - nftables integration # include $(TOPDIR)/rules.mk -PKG_NAME:=crowdsec-firewall-bouncer -PKG_VERSION:=0.0.34 +PKG_NAME:=secubox-app-cs-firewall-bouncer +PKG_VERSION:=0.0.31 PKG_RELEASE:=1 -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +# Source from upstream CrowdSec +# Note: v0.0.31 is the last version compatible with Go 1.23 (OpenWrt 24.10 SDK) +PKG_SOURCE:=crowdsec-firewall-bouncer-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/crowdsecurity/cs-firewall-bouncer/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=5c58f5cb9a8afc94520f62a39be290e8eea4c1a5bbacc5fea78ccfad9c8da232 +PKG_HASH:=c34963f0680ae296ae974d8f6444a2d1e2dd7617e7b05d4ad85c320529eec5f5 PKG_BUILD_DIR:=$(BUILD_DIR)/cs-firewall-bouncer-$(PKG_VERSION) @@ -30,27 +32,30 @@ GO_PKG:=github.com/crowdsecurity/cs-firewall-bouncer # Build version information GO_PKG_LDFLAGS_X:= \ - github.com/crowdsecurity/go-cs-lib/version.Tag=v$(PKG_VERSION)-openwrt \ + github.com/crowdsecurity/go-cs-lib/version.Tag=v$(PKG_VERSION)-secubox \ github.com/crowdsecurity/go-cs-lib/version.Timestamp=$(SOURCE_DATE_EPOCH) \ github.com/crowdsecurity/go-cs-lib/version.GoVersion=$(shell $(GO_STAGING_DIR)/bin/go version | cut -d" " -f3) include $(INCLUDE_DIR)/package.mk include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk -define Package/crowdsec-firewall-bouncer/Default +define Package/secubox-app-cs-firewall-bouncer/Default SECTION:=net CATEGORY:=Network - TITLE:=CrowdSec Firewall Bouncer + SUBMENU:=SecuBox + TITLE:=SecuBox CrowdSec Firewall Bouncer URL:=https://github.com/crowdsecurity/cs-firewall-bouncer endef -define Package/crowdsec-firewall-bouncer -$(call Package/crowdsec-firewall-bouncer/Default) +define Package/secubox-app-cs-firewall-bouncer +$(call Package/secubox-app-cs-firewall-bouncer/Default) DEPENDS:=$(GO_ARCH_DEPENDS) +nftables + PROVIDES:=crowdsec-firewall-bouncer + CONFLICTS:=crowdsec-firewall-bouncer endef -define Package/crowdsec-firewall-bouncer/description - CrowdSec Firewall Bouncer for OpenWrt/SecuBox. +define Package/secubox-app-cs-firewall-bouncer/description + SecuBox CrowdSec Firewall Bouncer for OpenWrt. Fetches decisions from CrowdSec Local API and enforces them using nftables. Supports both IPv4 and IPv6 blocking with @@ -61,15 +66,15 @@ define Package/crowdsec-firewall-bouncer/description - IPv4 and IPv6 support - Input and forward chain filtering - Interface-based filtering - - Automatic cleanup on stop + - Automatic restart on firewall reload - procd service management endef -define Package/crowdsec-firewall-bouncer/conffiles +define Package/secubox-app-cs-firewall-bouncer/conffiles /etc/config/crowdsec endef -define Package/crowdsec-firewall-bouncer/install +define Package/secubox-app-cs-firewall-bouncer/install $(call GoPackage/Package/Install/Bin,$(1)) $(INSTALL_DIR) $(1)/etc/config @@ -77,7 +82,11 @@ define Package/crowdsec-firewall-bouncer/install $(INSTALL_DIR) $(1)/etc/init.d $(INSTALL_BIN) ./files/crowdsec-firewall-bouncer.initd $(1)/etc/init.d/crowdsec-firewall-bouncer + + # Hotplug script to restart bouncer when firewall reloads + $(INSTALL_DIR) $(1)/etc/hotplug.d/iface + $(INSTALL_DATA) ./files/hotplug.d/99-crowdsec-bouncer $(1)/etc/hotplug.d/iface/99-crowdsec-bouncer endef -$(eval $(call GoBinPackage,crowdsec-firewall-bouncer)) -$(eval $(call BuildPackage,crowdsec-firewall-bouncer)) +$(eval $(call GoBinPackage,secubox-app-cs-firewall-bouncer)) +$(eval $(call BuildPackage,secubox-app-cs-firewall-bouncer)) diff --git a/package/secubox/crowdsec-firewall-bouncer/files/crowdsec-firewall-bouncer.initd b/package/secubox/secubox-app-cs-firewall-bouncer/files/crowdsec-firewall-bouncer.initd similarity index 90% rename from package/secubox/crowdsec-firewall-bouncer/files/crowdsec-firewall-bouncer.initd rename to package/secubox/secubox-app-cs-firewall-bouncer/files/crowdsec-firewall-bouncer.initd index c1e95547..d1007bd1 100644 --- a/package/secubox/crowdsec-firewall-bouncer/files/crowdsec-firewall-bouncer.initd +++ b/package/secubox/secubox-app-cs-firewall-bouncer/files/crowdsec-firewall-bouncer.initd @@ -7,6 +7,7 @@ USE_PROCD=1 START=99 +STOP=10 NAME=crowdsec-firewall-bouncer PROG=/usr/bin/cs-firewall-bouncer @@ -21,6 +22,8 @@ TABLE6="crowdsec6" service_triggers() { procd_add_reload_trigger crowdsec-firewall-bouncer procd_add_config_trigger "config.change" "crowdsec" /etc/init.d/crowdsec-firewall-bouncer reload + # Restart bouncer when firewall reloads to re-apply nftables rules + procd_add_reload_trigger firewall } init_yaml() { @@ -235,19 +238,37 @@ run_bouncer() { procd_set_param stderr 1 procd_set_param nice 10 - # Use ujail if available for security isolation - if [ -x "/sbin/ujail" ]; then - procd_add_jail cs-bouncer log - procd_add_jail_mount $VARCONFIG - procd_add_jail_mount_rw /var/log/ - procd_set_param no_new_privs 1 - fi + # Note: ujail disabled - bouncer needs direct nftables access + # to add/remove IPs from sets which requires CAP_NET_ADMIN + # if [ -x "/sbin/ujail" ]; then + # procd_add_jail cs-bouncer log + # procd_add_jail_mount $VARCONFIG + # procd_add_jail_mount_rw /var/log/ + # procd_set_param no_new_privs 1 + # fi procd_close_instance fi } +wait_for_firewall() { + # Wait for fw4/nftables to be ready (max 30 seconds) + local i=0 + while [ $i -lt 30 ]; do + if nft list tables >/dev/null 2>&1; then + return 0 + fi + sleep 1 + i=$((i + 1)) + done + logger -t crowdsec-bouncer "Warning: nftables not ready after 30s, starting anyway" + return 1 +} + start_service() { + # Wait for firewall/nftables to be ready + wait_for_firewall + config_load "${CONFIGURATION}" config_foreach run_bouncer bouncer } diff --git a/package/secubox/crowdsec-firewall-bouncer/files/crowdsec.config b/package/secubox/secubox-app-cs-firewall-bouncer/files/crowdsec.config similarity index 100% rename from package/secubox/crowdsec-firewall-bouncer/files/crowdsec.config rename to package/secubox/secubox-app-cs-firewall-bouncer/files/crowdsec.config diff --git a/package/secubox/secubox-app-cs-firewall-bouncer/files/hotplug.d/99-crowdsec-bouncer b/package/secubox/secubox-app-cs-firewall-bouncer/files/hotplug.d/99-crowdsec-bouncer new file mode 100644 index 00000000..5bd7bd61 --- /dev/null +++ b/package/secubox/secubox-app-cs-firewall-bouncer/files/hotplug.d/99-crowdsec-bouncer @@ -0,0 +1,31 @@ +#!/bin/sh +# CrowdSec Firewall Bouncer - Interface/Firewall hotplug handler +# Ensures bouncer's nftables rules are applied after network/firewall changes + +# Only act on interface up events for WAN +[ "$ACTION" = "ifup" ] || exit 0 +[ "$INTERFACE" = "wan" ] || [ "$INTERFACE" = "wan6" ] || exit 0 + +# Check if bouncer is enabled +. /lib/functions.sh +config_load crowdsec + +is_enabled() { + local section="$1" + local enabled + config_get_bool enabled "$section" enabled 0 + [ "$enabled" -eq 1 ] && return 0 + return 1 +} + +bouncer_enabled=0 +config_foreach is_enabled bouncer && bouncer_enabled=1 + +[ "$bouncer_enabled" -eq 1 ] || exit 0 + +# Check if crowdsec tables exist - if not, bouncer needs restart +if ! nft list table ip crowdsec >/dev/null 2>&1; then + logger -t crowdsec-bouncer "WAN up but crowdsec nftables missing, restarting bouncer" + sleep 2 + /etc/init.d/crowdsec-firewall-bouncer restart +fi diff --git a/package/secubox/secubox-auth-logger/files/secubox-private-ip-whitelist.yaml b/package/secubox/secubox-auth-logger/files/secubox-private-ip-whitelist.yaml deleted file mode 100644 index 9c444d52..00000000 --- a/package/secubox/secubox-auth-logger/files/secubox-private-ip-whitelist.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# CrowdSec Whitelist for Private IP Ranges -# Prevents blocking of internal network addresses (RFC1918) -# These IPs should never be banned as they are local network devices - -name: secubox/private-ip-whitelist -description: "Whitelist private/internal IP ranges to prevent self-blocking" -whitelist: - reason: "Private IP addresses (RFC1918) - local network devices" - ip: - - "127.0.0.0/8" # Localhost - - "10.0.0.0/8" # Class A private - - "172.16.0.0/12" # Class B private - - "192.168.0.0/16" # Class C private - - "169.254.0.0/16" # Link-local - - "::1/128" # IPv6 localhost - - "fe80::/10" # IPv6 link-local - - "fc00::/7" # IPv6 unique local diff --git a/package/secubox/secubox-crowdsec-setup/Makefile b/package/secubox/secubox-crowdsec-setup/Makefile deleted file mode 100644 index d9596748..00000000 --- a/package/secubox/secubox-crowdsec-setup/Makefile +++ /dev/null @@ -1,53 +0,0 @@ -# SPDX-License-Identifier: MIT -# -# SecuBox CrowdSec Setup Package -# Copyright (C) 2025 CyberMind.fr - Gandalf -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=secubox-crowdsec-setup -PKG_VERSION:=1.0.0 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Gerald Kerma -PKG_LICENSE:=MIT - -include $(INCLUDE_DIR)/package.mk - -define Package/secubox-crowdsec-setup - SECTION:=secubox - CATEGORY:=SecuBox - SUBMENU:=Security - TITLE:=SecuBox CrowdSec Setup Utility - DEPENDS:=+crowdsec +crowdsec-firewall-bouncer +syslog-ng - PKGARCH:=all -endef - -define Package/secubox-crowdsec-setup/description - Script d'installation automatisee de CrowdSec pour SecuBox. - Configure syslog-ng pour le forwarding des logs vers CrowdSec, - installe les collections de securite, et configure le bouncer - nftables pour fw4. -endef - -define Build/Compile -endef - -define Package/secubox-crowdsec-setup/install - $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) ./files/usr/sbin/secubox-crowdsec-setup $(1)/usr/sbin/ - - $(INSTALL_DIR) $(1)/etc/secubox/backups/crowdsec -endef - -define Package/secubox-crowdsec-setup/postinst -#!/bin/sh -[ -n "$${IPKG_INSTROOT}" ] || { - echo "SecuBox CrowdSec Setup installe." - echo "Executez 'secubox-crowdsec-setup' pour configurer CrowdSec." -} -exit 0 -endef - -$(eval $(call BuildPackage,secubox-crowdsec-setup)) diff --git a/package/secubox/secubox-crowdsec-setup/files/usr/sbin/secubox-crowdsec-setup b/package/secubox/secubox-crowdsec-setup/files/usr/sbin/secubox-crowdsec-setup deleted file mode 100644 index 0b5728ad..00000000 --- a/package/secubox/secubox-crowdsec-setup/files/usr/sbin/secubox-crowdsec-setup +++ /dev/null @@ -1,1052 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: MIT -# SecuBox CrowdSec Setup Script pour OpenWrt 24.10+ -# Copyright (C) 2025 CyberMind.fr - Gandalf -# -# Script d'installation automatisee de CrowdSec avec : -# - syslog-ng4 pour le forwarding des logs -# - crowdsec-firewall-bouncer-nftables pour fw4 -# - Integration complete avec SecuBox -# -# Usage: secubox-crowdsec-setup [--uninstall|--status|--repair] - -set -e - -# ============================================================================= -# CONFIGURATION -# ============================================================================= - -VERSION="1.0.0" -SCRIPT_NAME="secubox-crowdsec-setup" -LOG_TAG="secubox-crowdsec" - -# Repertoires -CROWDSEC_CONFIG_DIR="/etc/crowdsec" -CROWDSEC_DATA_DIR="/srv/crowdsec/data" -CROWDSEC_HUB_DIR="/etc/crowdsec/hub" -SYSLOG_NG_DIR="/etc/syslog-ng" -BACKUP_DIR="/etc/secubox/backups/crowdsec" - -# Ports et adresses -SYSLOG_LISTEN_ADDR="127.0.0.1" -SYSLOG_LISTEN_PORT="5140" -LAPI_LISTEN_ADDR="127.0.0.1" -LAPI_LISTEN_PORT="8080" - -# Prérequis -MIN_FLASH_MB=50 -MIN_RAM_MB=256 -MIN_OPENWRT_MAJOR=24 - -# Collections a installer -COLLECTIONS="crowdsecurity/linux crowdsecurity/sshd crowdsecurity/http-cve crowdsecurity/iptables" - -# Couleurs (si terminal supporte) -if [ -t 1 ]; then - RED='\033[0;31m' - GREEN='\033[0;32m' - YELLOW='\033[1;33m' - BLUE='\033[0;34m' - NC='\033[0m' -else - RED='' - GREEN='' - YELLOW='' - BLUE='' - NC='' -fi - -# ============================================================================= -# FONCTIONS UTILITAIRES -# ============================================================================= - -# Journalisation -log_info() { - printf "${GREEN}[INFO]${NC} %s\n" "$1" - logger -t "$LOG_TAG" -p info "$1" -} - -log_warn() { - printf "${YELLOW}[WARN]${NC} %s\n" "$1" >&2 - logger -t "$LOG_TAG" -p warning "$1" -} - -log_error() { - printf "${RED}[ERREUR]${NC} %s\n" "$1" >&2 - logger -t "$LOG_TAG" -p err "$1" -} - -log_step() { - printf "\n${BLUE}==> %s${NC}\n" "$1" -} - -# Verification de commande disponible -check_cmd() { - command -v "$1" >/dev/null 2>&1 -} - -# Lecture securisee d'une valeur UCI -uci_get() { - uci -q get "$1" 2>/dev/null || echo "" -} - -# Ecriture UCI avec creation de section si necessaire -uci_set() { - uci -q set "$1" 2>/dev/null -} - -# Verification que le script tourne en root -check_root() { - if [ "$(id -u)" != "0" ]; then - log_error "Ce script doit etre execute en tant que root" - exit 1 - fi -} - -# Detection de l'architecture -detect_arch() { - ARCH=$(uname -m) - case "$ARCH" in - aarch64) - ARCH_NAME="arm64" - ;; - armv7l|armv7) - ARCH_NAME="armv7" - ;; - x86_64) - ARCH_NAME="x86_64" - ;; - mips|mipsel) - ARCH_NAME="mips" - ;; - *) - ARCH_NAME="$ARCH" - ;; - esac - log_info "Architecture detectee: $ARCH_NAME ($ARCH)" -} - -# Detection de la version OpenWrt -detect_openwrt_version() { - if [ -f /etc/openwrt_release ]; then - . /etc/openwrt_release - OPENWRT_VERSION="${DISTRIB_RELEASE:-unknown}" - OPENWRT_CODENAME="${DISTRIB_CODENAME:-unknown}" - - # Extraire le numero de version majeur - OPENWRT_MAJOR=$(echo "$OPENWRT_VERSION" | cut -d'.' -f1) - - log_info "Version OpenWrt: $OPENWRT_VERSION ($OPENWRT_CODENAME)" - else - log_error "Fichier /etc/openwrt_release non trouve. Est-ce bien OpenWrt?" - exit 1 - fi -} - -# Verification des prerequis materiels -check_prerequisites() { - log_step "Verification des prerequis" - - local errors=0 - - # Verification version OpenWrt - if [ "$OPENWRT_MAJOR" -lt "$MIN_OPENWRT_MAJOR" ]; then - log_error "OpenWrt $MIN_OPENWRT_MAJOR+ requis (detecte: $OPENWRT_VERSION)" - errors=$((errors + 1)) - else - log_info "Version OpenWrt OK: $OPENWRT_VERSION" - fi - - # Verification espace flash (en Mo) - # Utiliser df sur /overlay qui represente l'espace disponible - if [ -d /overlay ]; then - FLASH_AVAIL=$(df -m /overlay 2>/dev/null | awk 'NR==2 {print $4}') - else - # Fallback sur / - FLASH_AVAIL=$(df -m / 2>/dev/null | awk 'NR==2 {print $4}') - fi - - if [ -n "$FLASH_AVAIL" ] && [ "$FLASH_AVAIL" -lt "$MIN_FLASH_MB" ]; then - log_error "Espace flash insuffisant: ${FLASH_AVAIL}Mo disponible, ${MIN_FLASH_MB}Mo requis" - errors=$((errors + 1)) - else - log_info "Espace flash OK: ${FLASH_AVAIL:-?}Mo disponible" - fi - - # Verification RAM - RAM_TOTAL=$(awk '/MemTotal/ {print int($2/1024)}' /proc/meminfo) - if [ "$RAM_TOTAL" -lt "$MIN_RAM_MB" ]; then - log_error "RAM insuffisante: ${RAM_TOTAL}Mo detecte, ${MIN_RAM_MB}Mo requis" - errors=$((errors + 1)) - else - log_info "RAM OK: ${RAM_TOTAL}Mo" - fi - - # Verification nftables/fw4 - if ! check_cmd nft; then - log_error "nftables non disponible. fw4 requis pour OpenWrt 24.10+" - errors=$((errors + 1)) - else - log_info "nftables OK" - fi - - # Verification connectivite Internet - if ! ping -c 1 -W 3 downloads.openwrt.org >/dev/null 2>&1; then - log_warn "Pas de connectivite Internet detectee" - # Pas fatal, l'utilisateur peut avoir des paquets locaux - else - log_info "Connectivite Internet OK" - fi - - if [ "$errors" -gt 0 ]; then - log_error "$errors erreur(s) de prerequis. Installation annulee." - exit 1 - fi - - log_info "Tous les prerequis sont satisfaits" -} - -# ============================================================================= -# SAUVEGARDE ET RESTAURATION -# ============================================================================= - -backup_configs() { - log_step "Sauvegarde des configurations existantes" - - BACKUP_TIMESTAMP=$(date +%Y%m%d_%H%M%S) - BACKUP_PATH="${BACKUP_DIR}/${BACKUP_TIMESTAMP}" - - mkdir -p "$BACKUP_PATH" - - # Sauvegarder les configs existantes - [ -d "$CROWDSEC_CONFIG_DIR" ] && cp -a "$CROWDSEC_CONFIG_DIR" "$BACKUP_PATH/" 2>/dev/null || true - [ -d "$SYSLOG_NG_DIR" ] && cp -a "$SYSLOG_NG_DIR" "$BACKUP_PATH/" 2>/dev/null || true - [ -f /etc/config/system ] && cp /etc/config/system "$BACKUP_PATH/" 2>/dev/null || true - - # Sauvegarder la liste des paquets installes - opkg list-installed > "$BACKUP_PATH/packages.list" 2>/dev/null || true - - log_info "Sauvegarde creee dans $BACKUP_PATH" - - # Garder les 5 dernieres sauvegardes - ls -dt "${BACKUP_DIR}"/*/ 2>/dev/null | tail -n +6 | xargs rm -rf 2>/dev/null || true -} - -rollback() { - log_error "Erreur detectee, tentative de rollback..." - - # Trouver la derniere sauvegarde - LAST_BACKUP=$(ls -dt "${BACKUP_DIR}"/*/ 2>/dev/null | head -1) - - if [ -z "$LAST_BACKUP" ]; then - log_error "Aucune sauvegarde disponible pour rollback" - return 1 - fi - - log_info "Restauration depuis $LAST_BACKUP" - - # Arreter les services - /etc/init.d/crowdsec stop 2>/dev/null || true - /etc/init.d/crowdsec-firewall-bouncer stop 2>/dev/null || true - /etc/init.d/syslog-ng stop 2>/dev/null || true - - # Restaurer les configs - [ -d "$LAST_BACKUP/crowdsec" ] && cp -a "$LAST_BACKUP/crowdsec"/* "$CROWDSEC_CONFIG_DIR/" 2>/dev/null || true - [ -d "$LAST_BACKUP/syslog-ng" ] && cp -a "$LAST_BACKUP/syslog-ng"/* "$SYSLOG_NG_DIR/" 2>/dev/null || true - [ -f "$LAST_BACKUP/system" ] && cp "$LAST_BACKUP/system" /etc/config/system 2>/dev/null || true - - # Reactiver logd si necessaire - /etc/init.d/log enable 2>/dev/null || true - /etc/init.d/log start 2>/dev/null || true - - log_warn "Rollback effectue. Verifiez l'etat du systeme." -} - -# ============================================================================= -# INSTALLATION DES PAQUETS -# ============================================================================= - -install_packages() { - log_step "Installation des paquets" - - # Mise a jour de la liste des paquets - log_info "Mise a jour de la liste des paquets..." - opkg update || { - log_error "Echec de la mise a jour opkg" - return 1 - } - - # Liste des paquets a installer - # Note: syslog-ng4 pour OpenWrt 24.10+ (pas syslog-ng3) - PACKAGES="crowdsec crowdsec-firewall-bouncer-nftables syslog-ng4" - - # Installation des paquets - for pkg in $PACKAGES; do - log_info "Installation de $pkg..." - if opkg install "$pkg"; then - log_info "$pkg installe avec succes" - else - # Verifier si deja installe - if opkg list-installed | grep -q "^$pkg "; then - log_warn "$pkg deja installe" - else - log_error "Echec installation de $pkg" - return 1 - fi - fi - done - - # Verifier que cscli est disponible - if ! check_cmd cscli; then - log_error "cscli non disponible apres installation" - return 1 - fi - - log_info "Tous les paquets installes avec succes" -} - -# ============================================================================= -# CONFIGURATION SYSLOG-NG4 -# ============================================================================= - -configure_syslog_ng() { - log_step "Configuration de syslog-ng4" - - mkdir -p "$SYSLOG_NG_DIR" - mkdir -p /tmp/log - - # Configuration principale syslog-ng - cat > "${SYSLOG_NG_DIR}/syslog-ng.conf" << 'SYSLOGCONF' -# Configuration syslog-ng4 pour SecuBox/CrowdSec -# Genere automatiquement par secubox-crowdsec-setup -# Ne pas modifier manuellement - utiliser UCI - -@version: 4.2 -@include "scl.conf" - -# Options globales -options { - chain_hostnames(off); - flush_lines(0); - use_dns(no); - use_fqdn(no); - dns_cache(no); - owner("root"); - group("root"); - perm(0640); - stats_freq(0); - bad_hostname("^gconfd$"); - keep_hostname(yes); - create_dirs(yes); -}; - -# Sources -# Source systeme principale (socket Unix) -source s_sys { - unix-dgram("/dev/log"); - internal(); -}; - -# Source kernel -source s_kernel { - file("/proc/kmsg" program_override("kernel")); -}; - -# Destinations -# Destination CrowdSec (UDP local) -destination d_crowdsec { - syslog("127.0.0.1" - transport("udp") - port(5140) - ); -}; - -# Destination fichier debug (optionnel, dans tmpfs) -destination d_messages { - file("/tmp/log/messages" - template("${DATE} ${HOST} ${MSGHDR}${MSG}\n") - create_dirs(yes) - ); -}; - -# Destination kernel log -destination d_kern { - file("/tmp/log/kern.log" - template("${DATE} ${HOST} ${MSGHDR}${MSG}\n") - ); -}; - -# Destination auth log (SSH, etc.) -destination d_auth { - file("/tmp/log/auth.log" - template("${DATE} ${HOST} ${MSGHDR}${MSG}\n") - ); -}; - -# Filtres -filter f_kern { facility(kern); }; -filter f_auth { facility(auth) or facility(authpriv); }; -filter f_messages { level(info..emerg) and not facility(auth, authpriv, kern); }; - -# Log paths -# Tout vers CrowdSec -log { source(s_sys); source(s_kernel); destination(d_crowdsec); }; - -# Fichiers locaux pour debug -log { source(s_sys); filter(f_messages); destination(d_messages); }; -log { source(s_kernel); filter(f_kern); destination(d_kern); }; -log { source(s_sys); filter(f_auth); destination(d_auth); }; -SYSLOGCONF - - log_info "Configuration syslog-ng4 creee" - - # Desactiver logd natif OpenWrt - log_info "Desactivation de logd natif..." - /etc/init.d/log stop 2>/dev/null || true - /etc/init.d/log disable 2>/dev/null || true - - # Configurer UCI pour desactiver le log buffer interne - uci_set system.@system[0].log_size='0' - uci_set system.@system[0].log_buffer_size='0' - uci commit system 2>/dev/null || true - - # Activer et demarrer syslog-ng - /etc/init.d/syslog-ng enable - /etc/init.d/syslog-ng start || { - log_error "Echec demarrage syslog-ng" - return 1 - } - - # Verifier que syslog-ng fonctionne - sleep 2 - if pgrep -f "syslog-ng" >/dev/null; then - log_info "syslog-ng4 demarre avec succes" - else - log_error "syslog-ng4 ne semble pas fonctionner" - return 1 - fi -} - -# ============================================================================= -# CONFIGURATION CROWDSEC -# ============================================================================= - -configure_crowdsec() { - log_step "Configuration de CrowdSec" - - mkdir -p "$CROWDSEC_CONFIG_DIR" - mkdir -p "$CROWDSEC_DATA_DIR" - mkdir -p "$CROWDSEC_HUB_DIR" - mkdir -p "${CROWDSEC_CONFIG_DIR}/acquis.d" - - # Configuration acquisition syslog - cat > "${CROWDSEC_CONFIG_DIR}/acquis.d/syslog.yaml" << ACQUISCONF -# Acquisition syslog pour OpenWrt/SecuBox -# Source: syslog-ng4 via UDP - -source: syslog -listen_addr: ${SYSLOG_LISTEN_ADDR} -listen_port: ${SYSLOG_LISTEN_PORT} -labels: - type: syslog -ACQUISCONF - - log_info "Configuration acquisition syslog creee" - - # Verifier/corriger config.yaml - if [ -f "${CROWDSEC_CONFIG_DIR}/config.yaml" ]; then - # S'assurer que les chemins sont corrects - sed -i "s|data_dir:.*|data_dir: ${CROWDSEC_DATA_DIR}/|" "${CROWDSEC_CONFIG_DIR}/config.yaml" - sed -i "s|db_path:.*|db_path: ${CROWDSEC_DATA_DIR}/crowdsec.db|" "${CROWDSEC_CONFIG_DIR}/config.yaml" - log_info "Configuration CrowdSec mise a jour" - fi - - # Creer la configuration UCI pour CrowdSec - if [ ! -f /etc/config/crowdsec ]; then - cat > /etc/config/crowdsec << 'UCICONF' -config crowdsec 'crowdsec' - option enabled '1' - option data_dir '/srv/crowdsec/data' - option db_path '/srv/crowdsec/data/crowdsec.db' - -config acquisition 'acquisition' - option syslog_enabled '1' - option firewall_enabled '1' - option ssh_enabled '1' - option http_enabled '0' - -config hub 'hub' - option auto_install '1' - option collections 'crowdsecurity/linux crowdsecurity/sshd crowdsecurity/iptables' - option update_interval '7' - -config bouncer 'bouncer' - option enabled '1' - option ipv4 '1' - option ipv6 '1' - option deny_action 'drop' - option deny_log '1' - option update_frequency '10s' - option filter_input '1' - option filter_forward '1' -UCICONF - log_info "Configuration UCI CrowdSec creee" - fi -} - -# ============================================================================= -# ENREGISTREMENT CAPI ET INSTALLATION COLLECTIONS -# ============================================================================= - -register_and_setup_hub() { - log_step "Enregistrement CAPI et installation des collections" - - # Demarrer CrowdSec temporairement pour les commandes cscli - /etc/init.d/crowdsec start 2>/dev/null || true - sleep 3 - - # Enregistrement CAPI (Central API) - log_info "Enregistrement aupres de la CAPI CrowdSec..." - if cscli capi register 2>/dev/null; then - log_info "Enregistrement CAPI reussi" - else - log_warn "Echec enregistrement CAPI (peut-etre deja enregistre)" - fi - - # Mise a jour du hub - log_info "Mise a jour du hub CrowdSec..." - cscli hub update || log_warn "Echec mise a jour hub" - - # Installation des collections - log_info "Installation des collections..." - for collection in $COLLECTIONS; do - log_info "Installation de $collection..." - if cscli collections install "$collection" 2>/dev/null; then - log_info "Collection $collection installee" - else - log_warn "Echec installation de $collection (peut-etre deja installee)" - fi - done - - # Lister les collections installees - log_info "Collections installees:" - cscli collections list 2>/dev/null || true -} - -# ============================================================================= -# CONFIGURATION FIREWALL BOUNCER -# ============================================================================= - -configure_bouncer() { - log_step "Configuration du firewall bouncer" - - # Generer la cle API pour le bouncer - log_info "Generation de la cle API bouncer..." - - # Supprimer l'ancien bouncer s'il existe - cscli bouncers delete crowdsec-firewall-bouncer 2>/dev/null || true - - # Creer le nouveau bouncer et recuperer la cle - API_KEY=$(cscli bouncers add crowdsec-firewall-bouncer -o raw 2>/dev/null) - - if [ -z "$API_KEY" ] || [ "${#API_KEY}" -lt 10 ]; then - log_error "Echec generation de la cle API bouncer" - return 1 - fi - - log_info "Cle API bouncer generee" - - # Configuration du bouncer nftables - mkdir -p /etc/crowdsec/bouncers - - cat > /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml << BOUNCERCONF -# Configuration Firewall Bouncer pour OpenWrt/SecuBox -# Genere automatiquement par secubox-crowdsec-setup - -mode: nftables -pid_dir: /var/run/ -update_frequency: 10s -daemonize: true -log_mode: file -log_dir: /var/log/ -log_level: info -log_compression: true -log_max_size: 10 -log_max_backups: 3 -log_max_age: 30 - -api_url: http://${LAPI_LISTEN_ADDR}:${LAPI_LISTEN_PORT}/ -api_key: ${API_KEY} - -disable_ipv6: false - -# Configuration nftables optimisee pour fw4 -nftables: - ipv4: - enabled: true - set-only: true - table: crowdsec - chain: crowdsec-chain - priority: -10 - ipv6: - enabled: true - set-only: true - table: crowdsec6 - chain: crowdsec6-chain - priority: -10 - -deny_action: drop -deny_log: true -deny_log_prefix: "crowdsec: " - -# Timers -blacklists_ipv4: crowdsec-blacklists -blacklists_ipv6: crowdsec6-blacklists -BOUNCERCONF - - log_info "Configuration bouncer creee" - - # Sauvegarder la cle API dans UCI - uci_set crowdsec.bouncer.api_key="$API_KEY" - uci commit crowdsec 2>/dev/null || true -} - -# ============================================================================= -# CONFIGURATION WHITELIST -# ============================================================================= - -configure_whitelist() { - log_step "Configuration des whitelists" - - # Creer un fichier de whitelist pour les reseaux locaux - cat > "${CROWDSEC_CONFIG_DIR}/parsers/s02-enrich/secubox-whitelist.yaml" << 'WHITELIST' -# Whitelist SecuBox - Reseaux locaux -# Ne pas bannir les adresses RFC1918 et link-local - -name: secubox/whitelists -description: "Whitelist des reseaux locaux SecuBox" -whitelist: - reason: "Reseau local SecuBox" - ip: - - "127.0.0.0/8" - - "10.0.0.0/8" - - "172.16.0.0/12" - - "192.168.0.0/16" - - "169.254.0.0/16" - - "::1/128" - - "fe80::/10" - - "fc00::/7" -WHITELIST - - log_info "Whitelist reseaux locaux creee" -} - -# ============================================================================= -# DEMARRAGE DES SERVICES -# ============================================================================= - -start_services() { - log_step "Demarrage des services" - - # Ordre de demarrage: syslog-ng -> crowdsec -> bouncer - - # Redemarrer syslog-ng pour s'assurer qu'il fonctionne - log_info "Redemarrage syslog-ng..." - /etc/init.d/syslog-ng restart || log_warn "Probleme redemarrage syslog-ng" - sleep 2 - - # Demarrer CrowdSec - log_info "Demarrage CrowdSec..." - /etc/init.d/crowdsec enable - /etc/init.d/crowdsec restart || { - log_error "Echec demarrage CrowdSec" - return 1 - } - sleep 3 - - # Verifier que LAPI est disponible - local retries=10 - while [ $retries -gt 0 ]; do - if cscli lapi status >/dev/null 2>&1; then - log_info "LAPI CrowdSec disponible" - break - fi - retries=$((retries - 1)) - sleep 1 - done - - if [ $retries -eq 0 ]; then - log_error "LAPI CrowdSec non disponible apres 10 secondes" - return 1 - fi - - # Demarrer le bouncer - log_info "Demarrage du firewall bouncer..." - /etc/init.d/crowdsec-firewall-bouncer enable - /etc/init.d/crowdsec-firewall-bouncer restart || { - log_error "Echec demarrage bouncer" - return 1 - } - sleep 2 - - # Verifier que les services tournent - log_info "Verification des services..." - - local all_ok=1 - - if pgrep -f "syslog-ng" >/dev/null; then - log_info " syslog-ng: OK" - else - log_error " syslog-ng: ECHEC" - all_ok=0 - fi - - if pgrep -x crowdsec >/dev/null; then - log_info " crowdsec: OK" - else - log_error " crowdsec: ECHEC" - all_ok=0 - fi - - if pgrep -f "crowdsec-firewall-bouncer" >/dev/null; then - log_info " bouncer: OK" - else - log_error " bouncer: ECHEC" - all_ok=0 - fi - - # Verifier les tables nftables - if nft list tables 2>/dev/null | grep -q "crowdsec"; then - log_info " nftables crowdsec: OK" - else - log_warn " nftables crowdsec: Tables non creees (normal au premier demarrage)" - fi - - if [ "$all_ok" -eq 0 ]; then - return 1 - fi -} - -# ============================================================================= -# VERIFICATION ET RAPPORT -# ============================================================================= - -verify_installation() { - log_step "Verification de l'installation" - - local errors=0 - - # Test connectivite CAPI - log_info "Test connectivite CAPI..." - if cscli capi status 2>/dev/null | grep -qi "online\|connected"; then - log_info " CAPI: Connecte" - else - log_warn " CAPI: Deconnecte (verifier la connectivite Internet)" - fi - - # Afficher les metriques - log_info "Metriques CrowdSec:" - cscli metrics 2>/dev/null | head -30 || log_warn " Impossible de recuperer les metriques" - - # Lister les bouncers - log_info "Bouncers enregistres:" - cscli bouncers list 2>/dev/null || log_warn " Impossible de lister les bouncers" - - # Verifier l'acquisition - log_info "Sources d'acquisition:" - cscli metrics show acquisition 2>/dev/null | head -10 || true -} - -generate_report() { - log_step "Rapport d'installation" - - REPORT_FILE="/tmp/secubox-crowdsec-install-report.txt" - - cat > "$REPORT_FILE" << REPORT -================================================================================ - RAPPORT D'INSTALLATION SECUBOX CROWDSEC -================================================================================ -Date: $(date) -Version script: $VERSION -Systeme: OpenWrt $OPENWRT_VERSION ($OPENWRT_CODENAME) -Architecture: $ARCH_NAME - -SERVICES INSTALLES: -------------------- -$(opkg list-installed | grep -E "crowdsec|syslog-ng" || echo "Erreur listing paquets") - -STATUT SERVICES: ----------------- -syslog-ng: $(pgrep -f syslog-ng >/dev/null && echo "ACTIF" || echo "INACTIF") -crowdsec: $(pgrep -x crowdsec >/dev/null && echo "ACTIF" || echo "INACTIF") -bouncer: $(pgrep -f crowdsec-firewall-bouncer >/dev/null && echo "ACTIF" || echo "INACTIF") - -COLLECTIONS INSTALLEES: ------------------------ -$(cscli collections list 2>/dev/null || echo "Erreur listing collections") - -BOUNCERS: ---------- -$(cscli bouncers list 2>/dev/null || echo "Erreur listing bouncers") - -TABLES NFTABLES: ----------------- -$(nft list tables 2>/dev/null | grep crowdsec || echo "Aucune table crowdsec") - -CONFIGURATION: --------------- -Syslog listen: ${SYSLOG_LISTEN_ADDR}:${SYSLOG_LISTEN_PORT} -LAPI listen: ${LAPI_LISTEN_ADDR}:${LAPI_LISTEN_PORT} -Data dir: ${CROWDSEC_DATA_DIR} -Config dir: ${CROWDSEC_CONFIG_DIR} - -COMMANDES UTILES: ------------------ -# Voir les decisions actives -cscli decisions list - -# Voir les alertes -cscli alerts list - -# Bannir une IP manuellement -cscli decisions add --ip --duration 24h --reason "Ban manuel" - -# Debannir une IP -cscli decisions delete --ip - -# Mettre a jour le hub -cscli hub update && cscli hub upgrade - -# Voir les metriques -cscli metrics - -# Logs CrowdSec -logread | grep crowdsec -cat /var/log/crowdsec.log - -================================================================================ -REPORT - - log_info "Rapport genere: $REPORT_FILE" - cat "$REPORT_FILE" -} - -# ============================================================================= -# DESINSTALLATION -# ============================================================================= - -uninstall() { - log_step "Desinstallation de CrowdSec SecuBox" - - # Confirmation - printf "ATTENTION: Ceci va supprimer CrowdSec et ses configurations.\n" - printf "Continuer? [y/N] " - read -r confirm - case "$confirm" in - [yY][eE][sS]|[yY]) - ;; - *) - log_info "Desinstallation annulee" - exit 0 - ;; - esac - - # Arreter les services - log_info "Arret des services..." - /etc/init.d/crowdsec-firewall-bouncer stop 2>/dev/null || true - /etc/init.d/crowdsec-firewall-bouncer disable 2>/dev/null || true - /etc/init.d/crowdsec stop 2>/dev/null || true - /etc/init.d/crowdsec disable 2>/dev/null || true - /etc/init.d/syslog-ng stop 2>/dev/null || true - /etc/init.d/syslog-ng disable 2>/dev/null || true - - # Supprimer les tables nftables - log_info "Suppression des tables nftables..." - nft delete table ip crowdsec 2>/dev/null || true - nft delete table ip6 crowdsec6 2>/dev/null || true - - # Desinstaller les paquets - log_info "Desinstallation des paquets..." - opkg remove crowdsec-firewall-bouncer-nftables 2>/dev/null || true - opkg remove crowdsec 2>/dev/null || true - opkg remove syslog-ng4 2>/dev/null || true - - # Reactiver logd - log_info "Reactivation de logd..." - /etc/init.d/log enable 2>/dev/null || true - /etc/init.d/log start 2>/dev/null || true - - # Optionnel: supprimer les configurations - printf "Supprimer les fichiers de configuration? [y/N] " - read -r confirm_conf - case "$confirm_conf" in - [yY][eE][sS]|[yY]) - rm -rf "$CROWDSEC_CONFIG_DIR" 2>/dev/null || true - rm -rf "$CROWDSEC_DATA_DIR" 2>/dev/null || true - rm -rf "$SYSLOG_NG_DIR" 2>/dev/null || true - rm -f /etc/config/crowdsec 2>/dev/null || true - log_info "Configurations supprimees" - ;; - *) - log_info "Configurations conservees" - ;; - esac - - log_info "Desinstallation terminee" -} - -# ============================================================================= -# STATUT -# ============================================================================= - -show_status() { - log_step "Statut CrowdSec SecuBox" - - printf "\n${BLUE}Services:${NC}\n" - printf " syslog-ng: " - if pgrep -f "syslog-ng" >/dev/null; then - printf "${GREEN}ACTIF${NC}\n" - else - printf "${RED}INACTIF${NC}\n" - fi - - printf " crowdsec: " - if pgrep -x crowdsec >/dev/null; then - printf "${GREEN}ACTIF${NC}\n" - else - printf "${RED}INACTIF${NC}\n" - fi - - printf " bouncer: " - if pgrep -f "crowdsec-firewall-bouncer" >/dev/null; then - printf "${GREEN}ACTIF${NC}\n" - else - printf "${RED}INACTIF${NC}\n" - fi - - printf "\n${BLUE}LAPI Status:${NC}\n" - cscli lapi status 2>/dev/null || printf " ${RED}Non disponible${NC}\n" - - printf "\n${BLUE}Decisions actives:${NC}\n" - cscli decisions list 2>/dev/null | head -10 || printf " Aucune ou erreur\n" - - printf "\n${BLUE}Tables nftables:${NC}\n" - nft list tables 2>/dev/null | grep crowdsec || printf " ${YELLOW}Aucune table crowdsec${NC}\n" -} - -# ============================================================================= -# REPARATION -# ============================================================================= - -repair() { - log_step "Reparation de l'installation CrowdSec" - - # Arreter les services - /etc/init.d/crowdsec-firewall-bouncer stop 2>/dev/null || true - /etc/init.d/crowdsec stop 2>/dev/null || true - - # Verifier/recreer les repertoires - mkdir -p "$CROWDSEC_DATA_DIR" - mkdir -p "$CROWDSEC_CONFIG_DIR" - - # Regenerer les credentials machine si necessaire - if [ ! -f "${CROWDSEC_CONFIG_DIR}/local_api_credentials.yaml" ]; then - log_info "Regeneration des credentials machine..." - cscli machines add localhost --auto --force 2>/dev/null || true - fi - - # Redemarrer CrowdSec - /etc/init.d/crowdsec start - sleep 3 - - # Verifier LAPI - if ! cscli lapi status >/dev/null 2>&1; then - log_error "LAPI toujours non disponible apres reparation" - return 1 - fi - - # Re-enregistrer le bouncer si necessaire - if ! cscli bouncers list 2>/dev/null | grep -q "crowdsec-firewall-bouncer"; then - log_info "Re-enregistrement du bouncer..." - configure_bouncer - fi - - # Redemarrer le bouncer - /etc/init.d/crowdsec-firewall-bouncer start - - log_info "Reparation terminee" - show_status -} - -# ============================================================================= -# MAIN -# ============================================================================= - -usage() { - cat << EOF -Usage: $SCRIPT_NAME [OPTIONS] - -Options: - --install Installation complete (defaut) - --uninstall Desinstallation complete - --status Afficher le statut des services - --repair Tenter de reparer une installation cassee - --help Afficher cette aide - -Version: $VERSION - -EOF -} - -main() { - check_root - detect_arch - detect_openwrt_version - - case "${1:-install}" in - --install|install) - log_step "Installation SecuBox CrowdSec v$VERSION" - - check_prerequisites - backup_configs - - # Piege pour rollback en cas d'erreur - trap 'rollback; exit 1' ERR - - install_packages - configure_syslog_ng - configure_crowdsec - register_and_setup_hub - configure_bouncer - configure_whitelist - start_services - verify_installation - generate_report - - # Desactiver le piege - trap - ERR - - log_step "Installation terminee avec succes!" - log_info "Consultez le rapport: /tmp/secubox-crowdsec-install-report.txt" - ;; - --uninstall|uninstall) - uninstall - ;; - --status|status) - show_status - ;; - --repair|repair) - repair - ;; - --help|-h|help) - usage - ;; - *) - log_error "Option inconnue: $1" - usage - exit 1 - ;; - esac -} - -main "$@"