a1a17e81a1
Includes updated JS challenge scripts with Claude-User whitelist, same-site referer bypass, Blackbox-Exporter allowed bot, and all new exporters, cheat sheets, and automation scripts.
445 lines
12 KiB
Bash
445 lines
12 KiB
Bash
#!/bin/bash
|
|
################################################################################
|
|
# Script Name: crowdsec-install.sh
|
|
# Version: 1.0
|
|
# Description: Automated CrowdSec installation with firewall bouncer,
|
|
# collection selection, allowlists, and Prometheus integration
|
|
# on Debian/Ubuntu and RHEL/Rocky/AlmaLinux
|
|
#
|
|
# Author: Phil Connor
|
|
# Contact: contact@mylinux.work
|
|
# Website: https://mylinux.work
|
|
# License: MIT
|
|
#
|
|
# Usage:
|
|
# sudo ./crowdsec-install.sh
|
|
# sudo ./crowdsec-install.sh --collections "sshd,nginx"
|
|
# sudo ./crowdsec-install.sh --allowlist "10.0.0.0/8" --prometheus
|
|
# sudo ./crowdsec-install.sh --dry-run
|
|
#
|
|
################################################################################
|
|
|
|
set -euo pipefail
|
|
|
|
# ============================================================================
|
|
# DEFAULTS
|
|
# ============================================================================
|
|
|
|
COLLECTIONS=""
|
|
ALLOWLIST=""
|
|
BOUNCER_TYPE="iptables"
|
|
PROMETHEUS=false
|
|
ENROLL_KEY=""
|
|
NO_BOUNCER=false
|
|
DRY_RUN=false
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m'
|
|
|
|
# ============================================================================
|
|
# HELPER FUNCTIONS
|
|
# ============================================================================
|
|
|
|
log_info() { echo -e "${GREEN}[INFO]${NC} $*"; }
|
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
|
log_error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
|
|
log_step() { echo -e "${CYAN}[STEP]${NC} $*"; }
|
|
|
|
show_usage() {
|
|
cat <<EOF
|
|
Usage: $0 [OPTIONS]
|
|
|
|
Installs and configures CrowdSec with firewall bouncer and collections.
|
|
|
|
OPTIONS:
|
|
--collections LIST Comma-separated collections (default: auto-detect)
|
|
--allowlist IPS Comma-separated trusted IP ranges to whitelist
|
|
--bouncer TYPE Bouncer type: iptables or nftables (default: iptables)
|
|
--prometheus Enable Prometheus metrics on :6060
|
|
--enroll KEY CrowdSec console enrollment key
|
|
--no-bouncer Install agent only, skip bouncer
|
|
--dry-run Show what would be done
|
|
-h, --help Show this help
|
|
|
|
EXAMPLES:
|
|
sudo $0
|
|
sudo $0 --collections "sshd,nginx,postfix"
|
|
sudo $0 --allowlist "10.0.0.0/8,192.168.1.0/24" --prometheus
|
|
sudo $0 --bouncer nftables --enroll "abc123"
|
|
|
|
EOF
|
|
exit 0
|
|
}
|
|
|
|
parse_args() {
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
-h|--help) show_usage ;;
|
|
--collections) COLLECTIONS="$2"; shift 2 ;;
|
|
--allowlist) ALLOWLIST="$2"; shift 2 ;;
|
|
--bouncer) BOUNCER_TYPE="$2"; shift 2 ;;
|
|
--prometheus) PROMETHEUS=true; shift ;;
|
|
--enroll) ENROLL_KEY="$2"; shift 2 ;;
|
|
--no-bouncer) NO_BOUNCER=true; shift ;;
|
|
--dry-run) DRY_RUN=true; shift ;;
|
|
*) log_error "Unknown option: $1"; exit 1 ;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
check_root() {
|
|
if [ "$(id -u)" -ne 0 ]; then
|
|
log_error "This script must be run as root"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# OS DETECTION
|
|
# ============================================================================
|
|
|
|
detect_os() {
|
|
if [ -f /etc/os-release ]; then
|
|
. /etc/os-release
|
|
OS_FAMILY=""
|
|
case "$ID" in
|
|
debian|ubuntu) OS_FAMILY="debian" ;;
|
|
rhel|centos|rocky|almalinux|fedora) OS_FAMILY="rhel" ;;
|
|
*)
|
|
if [ -n "${ID_LIKE:-}" ]; then
|
|
case "$ID_LIKE" in
|
|
*debian*|*ubuntu*) OS_FAMILY="debian" ;;
|
|
*rhel*|*centos*|*fedora*) OS_FAMILY="rhel" ;;
|
|
esac
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
if [ -z "$OS_FAMILY" ]; then
|
|
log_error "Unsupported OS: $ID"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "Detected OS: $PRETTY_NAME (family: $OS_FAMILY)"
|
|
else
|
|
log_error "Cannot detect OS — /etc/os-release not found"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# SERVICE DETECTION
|
|
# ============================================================================
|
|
|
|
detect_services() {
|
|
log_step "Detecting running services..."
|
|
local detected=()
|
|
|
|
# Always include base Linux collection
|
|
detected+=("crowdsecurity/linux")
|
|
|
|
# SSH
|
|
if systemctl is-active --quiet sshd 2>/dev/null || systemctl is-active --quiet ssh 2>/dev/null; then
|
|
detected+=("crowdsecurity/sshd")
|
|
log_info " Detected: SSH"
|
|
fi
|
|
|
|
# Nginx
|
|
if systemctl is-active --quiet nginx 2>/dev/null; then
|
|
detected+=("crowdsecurity/nginx")
|
|
log_info " Detected: Nginx"
|
|
fi
|
|
|
|
# Apache
|
|
if systemctl is-active --quiet apache2 2>/dev/null || systemctl is-active --quiet httpd 2>/dev/null; then
|
|
detected+=("crowdsecurity/apache2")
|
|
log_info " Detected: Apache"
|
|
fi
|
|
|
|
# Postfix
|
|
if systemctl is-active --quiet postfix 2>/dev/null; then
|
|
detected+=("crowdsecurity/postfix")
|
|
log_info " Detected: Postfix"
|
|
fi
|
|
|
|
# Dovecot
|
|
if systemctl is-active --quiet dovecot 2>/dev/null; then
|
|
detected+=("crowdsecurity/dovecot")
|
|
log_info " Detected: Dovecot"
|
|
fi
|
|
|
|
# MySQL/MariaDB
|
|
if systemctl is-active --quiet mysql 2>/dev/null || systemctl is-active --quiet mariadb 2>/dev/null; then
|
|
detected+=("crowdsecurity/mysql")
|
|
log_info " Detected: MySQL/MariaDB"
|
|
fi
|
|
|
|
# PostgreSQL
|
|
if systemctl is-active --quiet postgresql 2>/dev/null; then
|
|
detected+=("crowdsecurity/pgsql")
|
|
log_info " Detected: PostgreSQL"
|
|
fi
|
|
|
|
DETECTED_COLLECTIONS="${detected[*]}"
|
|
}
|
|
|
|
# ============================================================================
|
|
# INSTALLATION
|
|
# ============================================================================
|
|
|
|
add_repo_debian() {
|
|
log_step "Adding CrowdSec repository (Debian/Ubuntu)..."
|
|
|
|
if [ "$DRY_RUN" = true ]; then
|
|
log_info "[DRY RUN] Would add CrowdSec apt repository"
|
|
return
|
|
fi
|
|
|
|
apt-get update -qq
|
|
apt-get install -y -qq curl gnupg apt-transport-https >/dev/null 2>&1
|
|
|
|
curl -s https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.deb.sh | bash >/dev/null 2>&1
|
|
}
|
|
|
|
add_repo_rhel() {
|
|
log_step "Adding CrowdSec repository (RHEL/Rocky)..."
|
|
|
|
if [ "$DRY_RUN" = true ]; then
|
|
log_info "[DRY RUN] Would add CrowdSec yum repository"
|
|
return
|
|
fi
|
|
|
|
curl -s https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.rpm.sh | bash >/dev/null 2>&1
|
|
}
|
|
|
|
install_agent() {
|
|
log_step "Installing CrowdSec agent..."
|
|
|
|
if [ "$DRY_RUN" = true ]; then
|
|
log_info "[DRY RUN] Would install crowdsec package"
|
|
return
|
|
fi
|
|
|
|
case "$OS_FAMILY" in
|
|
debian) apt-get install -y -qq crowdsec >/dev/null 2>&1 ;;
|
|
rhel) dnf install -y -q crowdsec >/dev/null 2>&1 ;;
|
|
esac
|
|
|
|
systemctl enable --now crowdsec >/dev/null 2>&1
|
|
log_info "CrowdSec agent installed and running"
|
|
}
|
|
|
|
install_bouncer() {
|
|
if [ "$NO_BOUNCER" = true ]; then
|
|
log_info "Skipping bouncer installation (--no-bouncer)"
|
|
return
|
|
fi
|
|
|
|
local pkg="crowdsec-firewall-bouncer-${BOUNCER_TYPE}"
|
|
log_step "Installing bouncer: $pkg..."
|
|
|
|
if [ "$DRY_RUN" = true ]; then
|
|
log_info "[DRY RUN] Would install $pkg"
|
|
return
|
|
fi
|
|
|
|
case "$OS_FAMILY" in
|
|
debian) apt-get install -y -qq "$pkg" >/dev/null 2>&1 ;;
|
|
rhel) dnf install -y -q "$pkg" >/dev/null 2>&1 ;;
|
|
esac
|
|
|
|
systemctl enable --now "$pkg" >/dev/null 2>&1
|
|
log_info "Bouncer installed: $pkg"
|
|
}
|
|
|
|
# ============================================================================
|
|
# CONFIGURATION
|
|
# ============================================================================
|
|
|
|
install_collections() {
|
|
local collections_to_install=""
|
|
|
|
if [ -n "$COLLECTIONS" ]; then
|
|
# User-specified collections
|
|
IFS=',' read -ra cols <<< "$COLLECTIONS"
|
|
for col in "${cols[@]}"; do
|
|
col=$(echo "$col" | xargs)
|
|
# Add crowdsecurity/ prefix if not present
|
|
if [[ "$col" != */* ]]; then
|
|
col="crowdsecurity/$col"
|
|
fi
|
|
collections_to_install="$collections_to_install $col"
|
|
done
|
|
else
|
|
# Auto-detected collections
|
|
collections_to_install="$DETECTED_COLLECTIONS"
|
|
fi
|
|
|
|
log_step "Installing collections: $collections_to_install"
|
|
|
|
if [ "$DRY_RUN" = true ]; then
|
|
log_info "[DRY RUN] Would install: $collections_to_install"
|
|
return
|
|
fi
|
|
|
|
for col in $collections_to_install; do
|
|
if cscli collections install "$col" >/dev/null 2>&1; then
|
|
log_info " Installed: $col"
|
|
else
|
|
log_warn " Failed to install: $col"
|
|
fi
|
|
done
|
|
}
|
|
|
|
configure_allowlist() {
|
|
if [ -z "$ALLOWLIST" ]; then
|
|
return
|
|
fi
|
|
|
|
log_step "Configuring allowlist..."
|
|
|
|
if [ "$DRY_RUN" = true ]; then
|
|
log_info "[DRY RUN] Would whitelist: $ALLOWLIST"
|
|
return
|
|
fi
|
|
|
|
IFS=',' read -ra ips <<< "$ALLOWLIST"
|
|
for ip in "${ips[@]}"; do
|
|
ip=$(echo "$ip" | xargs)
|
|
if cscli decisions add --ip "$ip" --type whitelist --duration 87600h >/dev/null 2>&1; then
|
|
log_info " Whitelisted: $ip"
|
|
else
|
|
log_warn " Failed to whitelist: $ip"
|
|
fi
|
|
done
|
|
}
|
|
|
|
configure_prometheus() {
|
|
if [ "$PROMETHEUS" != true ]; then
|
|
return
|
|
fi
|
|
|
|
log_step "Enabling Prometheus metrics on :6060..."
|
|
|
|
if [ "$DRY_RUN" = true ]; then
|
|
log_info "[DRY RUN] Would enable Prometheus metrics"
|
|
return
|
|
fi
|
|
|
|
local config="/etc/crowdsec/config.yaml"
|
|
if [ -f "$config" ]; then
|
|
# Prometheus is enabled by default in CrowdSec, verify
|
|
if grep -q "prometheus:" "$config"; then
|
|
log_info "Prometheus metrics already configured"
|
|
fi
|
|
fi
|
|
|
|
log_info "Prometheus metrics available at http://localhost:6060/metrics"
|
|
}
|
|
|
|
enroll_console() {
|
|
if [ -z "$ENROLL_KEY" ]; then
|
|
return
|
|
fi
|
|
|
|
log_step "Enrolling with CrowdSec console..."
|
|
|
|
if [ "$DRY_RUN" = true ]; then
|
|
log_info "[DRY RUN] Would enroll with key: $ENROLL_KEY"
|
|
return
|
|
fi
|
|
|
|
if cscli console enroll "$ENROLL_KEY" >/dev/null 2>&1; then
|
|
log_info "Enrolled with CrowdSec console"
|
|
else
|
|
log_warn "Console enrollment failed — verify enrollment key"
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# VERIFICATION
|
|
# ============================================================================
|
|
|
|
verify_installation() {
|
|
log_step "Verifying installation..."
|
|
|
|
echo ""
|
|
|
|
# CrowdSec agent
|
|
if systemctl is-active --quiet crowdsec 2>/dev/null; then
|
|
log_info "✓ CrowdSec agent: running"
|
|
else
|
|
log_error "✗ CrowdSec agent: not running"
|
|
fi
|
|
|
|
# Bouncer
|
|
if [ "$NO_BOUNCER" != true ]; then
|
|
local bouncer_svc="crowdsec-firewall-bouncer-${BOUNCER_TYPE}"
|
|
if systemctl is-active --quiet "$bouncer_svc" 2>/dev/null; then
|
|
log_info "✓ Firewall bouncer: running"
|
|
else
|
|
log_error "✗ Firewall bouncer: not running"
|
|
fi
|
|
fi
|
|
|
|
# Collections
|
|
log_info "Installed collections:"
|
|
cscli collections list 2>/dev/null | grep -E "enabled|installed" || true
|
|
|
|
# Bouncers
|
|
log_info "Registered bouncers:"
|
|
cscli bouncers list 2>/dev/null || true
|
|
|
|
echo ""
|
|
log_info "Installation complete"
|
|
echo ""
|
|
log_info "Useful commands:"
|
|
echo " cscli decisions list — view active decisions"
|
|
echo " cscli alerts list — view recent alerts"
|
|
echo " cscli metrics — view metrics summary"
|
|
echo " cscli hub list — view installed hub items"
|
|
}
|
|
|
|
# ============================================================================
|
|
# MAIN
|
|
# ============================================================================
|
|
|
|
main() {
|
|
parse_args "$@"
|
|
check_root
|
|
detect_os
|
|
|
|
echo ""
|
|
log_info "=== CrowdSec Installation Script v1.0 ==="
|
|
echo ""
|
|
|
|
if [ "$DRY_RUN" = true ]; then
|
|
log_warn "DRY RUN MODE — no changes will be made"
|
|
echo ""
|
|
fi
|
|
|
|
detect_services
|
|
|
|
case "$OS_FAMILY" in
|
|
debian) add_repo_debian ;;
|
|
rhel) add_repo_rhel ;;
|
|
esac
|
|
|
|
install_agent
|
|
install_collections
|
|
configure_allowlist
|
|
install_bouncer
|
|
configure_prometheus
|
|
enroll_console
|
|
|
|
if [ "$DRY_RUN" != true ]; then
|
|
verify_installation
|
|
fi
|
|
}
|
|
|
|
main "$@"
|