#!/bin/bash ################################################################################ # Script Name: install-ossec.sh # Version: 1.0 # Description: Automated OSSEC HIDS installation — server or agent mode, # file integrity monitoring, rootkit detection, log analysis, # active response, email alerts, and syscheck configuration # on Debian/Ubuntu and RHEL/Rocky/AlmaLinux # # Author: Phil Connor # Contact: contact@mylinux.work # Website: https://mylinux.work # License: MIT # # Usage: # sudo ./install-ossec.sh --mode server # sudo ./install-ossec.sh --mode agent --server-ip 10.0.1.10 # sudo ./install-ossec.sh --mode local # sudo ./install-ossec.sh --mode server --email admin@example.com # sudo ./install-ossec.sh --dry-run --mode server # sudo ./install-ossec.sh --uninstall # ################################################################################ set -euo pipefail # ============================================================================ # DEFAULTS # ============================================================================ readonly VERSION="1.0" readonly SCRIPT_NAME="${0##*/}" readonly LOG_FILE="/var/log/ossec-install.log" INSTALL_MODE="" SERVER_IP="" EMAIL_ADDR="" EMAIL_SMTP="localhost" ACTIVE_RESPONSE=true SYSCHECK_FREQUENCY="21600" SYSCHECK_DIRS="/etc,/usr/bin,/usr/sbin,/bin,/sbin" ROOTCHECK=true LOG_ANALYSIS=true DRY_RUN=false UNINSTALL=false OSSEC_VERSION="3.7.0" OSSEC_DIR="/var/ossec" # OS detection OS_ID="" OS_VERSION="" PKG_MGR="" # 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} $*"; echo "[INFO] $(date '+%Y-%m-%d %H:%M:%S') $*" >> "$LOG_FILE" 2>/dev/null || true; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; echo "[WARN] $(date '+%Y-%m-%d %H:%M:%S') $*" >> "$LOG_FILE" 2>/dev/null || true; } log_error() { echo -e "${RED}[ERROR]${NC} $*" >&2; echo "[ERROR] $(date '+%Y-%m-%d %H:%M:%S') $*" >> "$LOG_FILE" 2>/dev/null || true; } log_step() { echo -e "${CYAN}[STEP]${NC} $*"; echo "[STEP] $(date '+%Y-%m-%d %H:%M:%S') $*" >> "$LOG_FILE" 2>/dev/null || true; } show_usage() { cat </dev/null || PKG_MGR="yum" ;; *) log_error "Unsupported OS: $OS_ID"; exit 1 ;; esac log_info "Detected OS: $OS_ID $OS_VERSION (package manager: $PKG_MGR)" } # ============================================================================ # DEPENDENCIES # ============================================================================ install_dependencies() { log_step "Installing build dependencies..." if $DRY_RUN; then log_info "[DRY RUN] Would install build dependencies" return fi case "$PKG_MGR" in apt) apt-get update -qq apt-get install -y -qq build-essential make gcc libevent-dev libpcre2-dev \ libssl-dev libsystemd-dev zlib1g-dev wget tar ;; dnf|yum) $PKG_MGR groupinstall -y "Development Tools" 2>/dev/null || true $PKG_MGR install -y -q gcc make libevent-devel pcre2-devel openssl-devel \ systemd-devel zlib-devel wget tar ;; esac log_info "Dependencies installed" } # ============================================================================ # DOWNLOAD AND COMPILE # ============================================================================ download_ossec() { log_step "Downloading OSSEC ${OSSEC_VERSION}..." if $DRY_RUN; then log_info "[DRY RUN] Would download OSSEC ${OSSEC_VERSION}" return fi local url="https://github.com/ossec/ossec-hids/archive/refs/tags/${OSSEC_VERSION}.tar.gz" local tmpdir="/tmp/ossec-build" rm -rf "$tmpdir" mkdir -p "$tmpdir" cd "$tmpdir" wget -q "$url" -O "ossec-${OSSEC_VERSION}.tar.gz" tar xzf "ossec-${OSSEC_VERSION}.tar.gz" log_info "Downloaded and extracted OSSEC ${OSSEC_VERSION}" } install_ossec() { log_step "Installing OSSEC in ${INSTALL_MODE} mode..." if $DRY_RUN; then log_info "[DRY RUN] Would install OSSEC as ${INSTALL_MODE}" return fi local tmpdir="/tmp/ossec-build/ossec-hids-${OSSEC_VERSION}" cd "$tmpdir" # Generate preloaded-vars.conf for non-interactive install cat > etc/preloaded-vars.conf <> etc/preloaded-vars.conf fi # Run the install ./install.sh log_info "OSSEC installed to ${OSSEC_DIR}" } # ============================================================================ # CONFIGURATION # ============================================================================ configure_ossec() { log_step "Configuring OSSEC..." if $DRY_RUN; then log_info "[DRY RUN] Would configure syscheck directories and rules" return fi local ossec_conf="${OSSEC_DIR}/etc/ossec.conf" if [ ! -f "$ossec_conf" ]; then log_warn "ossec.conf not found — skipping custom configuration" return fi # Update syscheck frequency if grep -q "" "$ossec_conf"; then sed -i "s|[0-9]*|${SYSCHECK_FREQUENCY}|g" "$ossec_conf" log_info "Set syscheck frequency to ${SYSCHECK_FREQUENCY} seconds" fi # Add additional syscheck directories IFS=',' read -ra DIRS <<< "$SYSCHECK_DIRS" for dir in "${DIRS[@]}"; do dir=$(echo "$dir" | xargs) if ! grep -q "${dir}<" "$ossec_conf" 2>/dev/null; then sed -i "/<\/syscheck>/i\\ ${dir}" "$ossec_conf" log_info "Added syscheck directory: ${dir}" fi done # Add common ignore paths to reduce noise local ignores=( "/etc/mtab" "/etc/resolv.conf" "/etc/adjtime" "/etc/mail/statistics" "/etc/random-seed" "/etc/sysstat" ) for ign in "${ignores[@]}"; do if ! grep -q "${ign}" "$ossec_conf" 2>/dev/null; then sed -i "/<\/syscheck>/i\\ ${ign}" "$ossec_conf" fi done log_info "OSSEC configuration updated" } # ============================================================================ # FIREWALL # ============================================================================ configure_firewall() { if [ "$INSTALL_MODE" != "server" ]; then return fi log_step "Opening OSSEC server port (1514/udp)..." if $DRY_RUN; then log_info "[DRY RUN] Would open port 1514/udp" return fi if command -v ufw &>/dev/null && ufw status | grep -q "active"; then ufw allow 1514/udp log_info "Opened port 1514/udp via ufw" elif command -v firewall-cmd &>/dev/null; then firewall-cmd --permanent --add-port=1514/udp firewall-cmd --reload log_info "Opened port 1514/udp via firewalld" elif command -v nft &>/dev/null; then nft add rule inet filter input udp dport 1514 accept 2>/dev/null || true log_info "Opened port 1514/udp via nftables" fi } # ============================================================================ # SERVICE # ============================================================================ start_ossec() { log_step "Starting OSSEC..." if $DRY_RUN; then log_info "[DRY RUN] Would start OSSEC" return fi "${OSSEC_DIR}/bin/ossec-control" start sleep 3 if "${OSSEC_DIR}/bin/ossec-control" status | grep -q "running"; then log_info "OSSEC is running" else log_warn "OSSEC may not have started — check ${OSSEC_DIR}/logs/ossec.log" fi } # ============================================================================ # VERIFICATION # ============================================================================ verify_installation() { log_step "Verifying installation..." if $DRY_RUN; then log_info "[DRY RUN] Installation summary:" echo " Mode: ${INSTALL_MODE}" echo " Directory: ${OSSEC_DIR}" echo " Syscheck freq: ${SYSCHECK_FREQUENCY}s" echo " Active response: ${ACTIVE_RESPONSE}" echo " Rootcheck: ${ROOTCHECK}" echo " Email: ${EMAIL_ADDR:-disabled}" [ "$INSTALL_MODE" = "agent" ] && echo " Server IP: ${SERVER_IP}" return fi echo "" echo "=== OSSEC Installation Summary ===" echo "Mode: ${INSTALL_MODE}" echo "Version: ${OSSEC_VERSION}" echo "Install dir: ${OSSEC_DIR}" echo "Active response: ${ACTIVE_RESPONSE}" echo "Rootcheck: ${ROOTCHECK}" echo "Syscheck freq: ${SYSCHECK_FREQUENCY}s ($(( SYSCHECK_FREQUENCY / 3600 ))h)" echo "" echo "=== Process Status ===" "${OSSEC_DIR}/bin/ossec-control" status echo "" echo "=== Syscheck Status ===" "${OSSEC_DIR}/bin/syscheck_control" -l 2>/dev/null | head -5 || echo "(syscheck not yet run)" echo "" if [ "$INSTALL_MODE" = "server" ]; then echo "=== Agent Management ===" echo "To add agents:" echo " ${OSSEC_DIR}/bin/manage_agents" echo "" fi echo "=== Useful Commands ===" echo " Status: ${OSSEC_DIR}/bin/ossec-control status" echo " Restart: ${OSSEC_DIR}/bin/ossec-control restart" echo " Logs: tail -f ${OSSEC_DIR}/logs/ossec.log" echo " Alerts: tail -f ${OSSEC_DIR}/logs/alerts/alerts.log" echo "" log_info "Installation complete. Logs: $LOG_FILE" } # ============================================================================ # UNINSTALL # ============================================================================ uninstall_ossec() { log_step "Uninstalling OSSEC..." if $DRY_RUN; then log_info "[DRY RUN] Would stop and remove OSSEC" return fi if [ -x "${OSSEC_DIR}/bin/ossec-control" ]; then "${OSSEC_DIR}/bin/ossec-control" stop 2>/dev/null || true fi if [ -d "$OSSEC_DIR" ]; then rm -rf "$OSSEC_DIR" log_info "Removed ${OSSEC_DIR}" fi # Remove ossec user/group userdel ossec 2>/dev/null || true userdel ossecm 2>/dev/null || true userdel ossecr 2>/dev/null || true groupdel ossec 2>/dev/null || true log_info "OSSEC uninstalled" exit 0 } # ============================================================================ # MAIN # ============================================================================ main() { parse_args "$@" echo "" echo "============================================" echo " OSSEC Install Script v${VERSION}" echo " https://mylinux.work" echo "============================================" echo "" check_root detect_os if $UNINSTALL; then uninstall_ossec fi install_dependencies download_ossec install_ossec configure_ossec configure_firewall start_ossec verify_installation } main "$@"