Set up comprehensive intrusion detection by integrating OSSEC HIDS with fail2ban for automated threat response. This advanced configuration provides real-time monitoring, log analysis, and automated IP blocking for enhanced server security.
Prerequisites
- Root or sudo access
- Basic knowledge of Linux security concepts
- Understanding of log file formats
- Familiarity with iptables firewall rules
What this solves
This tutorial shows you how to integrate OSSEC Host-based Intrusion Detection System (HIDS) with fail2ban to create a comprehensive security monitoring solution. OSSEC monitors system logs and file integrity while fail2ban automatically blocks suspicious IP addresses, creating a layered defense against intrusions and automated attacks.
Step-by-step configuration
Update system packages
Start by updating your package manager to ensure you get the latest security updates.
sudo apt update && sudo apt upgrade -y
Install OSSEC dependencies
Install the required packages for building OSSEC from source and running the system.
sudo apt install -y build-essential gcc make unzip sendmail inotify-tools wget libevent-dev libssl-dev libz-dev
Download and install OSSEC
Download the latest OSSEC release and compile it for your system.
cd /tmp
wget https://github.com/ossec/ossec-hids/archive/v3.7.0.tar.gz
tar -xzf v3.7.0.tar.gz
cd ossec-hids-3.7.0
Configure OSSEC installation
Run the interactive installation script and select server installation for local monitoring.
sudo ./install.sh
When prompted, select these options:
- Installation type: local
- Email notification: y (enter your email)
- SMTP server: localhost
- Firewall response: y
- System integrity check: y
- Rootkit detection: y
- Active response: y
Install fail2ban
Install fail2ban which will handle the automatic IP blocking based on OSSEC alerts.
sudo apt install -y fail2ban
Configure OSSEC for fail2ban integration
Modify OSSEC configuration to enable log output that fail2ban can parse.
yes
localhost
ossec@example.com
admin@example.com
yes
no
rules_config.xml
pam_rules.xml
sshd_rules.xml
telnetd_rules.xml
syslog_rules.xml
arpwatch_rules.xml
symantec-av_rules.xml
symantec-ws_rules.xml
pix_rules.xml
named_rules.xml
smbd_rules.xml
vsftpd_rules.xml
pure-ftpd_rules.xml
proftpd_rules.xml
ms_ftpd_rules.xml
ftpd_rules.xml
hordeimp_rules.xml
roundcube_rules.xml
wordpress_rules.xml
cimserver_rules.xml
vpopmail_rules.xml
vmpop3d_rules.xml
courier_rules.xml
web_rules.xml
web_appsec_rules.xml
apache_rules.xml
nginx_rules.xml
php_rules.xml
mysql_rules.xml
postgresql_rules.xml
ids_rules.xml
squid_rules.xml
firewall_rules.xml
cisco-ios_rules.xml
netscreenfw_rules.xml
sonicwall_rules.xml
postfix_rules.xml
sendmail_rules.xml
imapd_rules.xml
mailscanner_rules.xml
dovecot_rules.xml
ms-exchange_rules.xml
racoon_rules.xml
vpn_concentrator_rules.xml
spamd_rules.xml
msauth_rules.xml
mcafee_av_rules.xml
trend-osce_rules.xml
ms-se_rules.xml
zeus_rules.xml
solaris_bsm_rules.xml
vmware_rules.xml
ms_dhcp_rules.xml
asterisk_rules.xml
ossec_rules.xml
attack_rules.xml
local_rules.xml
79200
/etc,/usr/bin,/usr/sbin
/bin,/sbin,/boot
/etc/mtab
/etc/hosts.deny
/etc/mail/statistics
/etc/random-seed
/etc/random.seed
/etc/adjtime
/etc/httpd/logs
/etc/utmpx
/etc/wtmpx
/etc/cups/certs
/etc/dumpdates
/etc/svc/volatile
/var/ossec/etc/shared/rootkit_files.txt
/var/ossec/etc/shared/rootkit_trojans.txt
/var/ossec/etc/shared/system_audit_rcl.txt
/var/ossec/etc/shared/system_audit_ssh.txt
/var/ossec/etc/shared/cis_debian_linux_rcl.txt
syslog
/var/log/messages
syslog
/var/log/secure
syslog
/var/log/auth.log
apache
/var/log/apache2/access.log
apache
/var/log/apache2/error.log
no
/var/ossec/etc/wpk_root.pem
Create custom OSSEC rules for fail2ban integration
Add custom rules to detect specific attack patterns and generate alerts that fail2ban can process.
5716
sshd: brute force trying to get access to the system.
authentication_failures,pci_dss_10.2.4,pci_dss_10.2.5,
31151
HTTP brute force attack detected.
attack,pci_dss_10.2.4,pci_dss_10.2.5,
5503
Multiple authentication failures from same source.
authentication_failures,pci_dss_10.2.4,pci_dss_10.2.5,
4151
Port scan detected from same source.
recon,pci_dss_10.6.1,
Configure fail2ban jail for OSSEC
Create a custom jail configuration that monitors OSSEC alerts and blocks offending IPs.
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3
banaction = iptables-multiport
protocol = tcp
chain = INPUT
action_ = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
action_mw = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
%(mta)s-whois[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]
action_mwl = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
%(mta)s-whois-lines[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]
action = %(action_)s
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
[apache-auth]
enabled = true
port = http,https
filter = apache-auth
logpath = /var/log/apache2/*error.log
maxretry = 6
bantime = 3600
[apache-badbots]
enabled = true
port = http,https
filter = apache-badbots
logpath = /var/log/apache2/*error.log
maxretry = 2
bantime = 86400
[apache-noscript]
enabled = true
port = http,https
filter = apache-noscript
logpath = /var/log/apache2/*error.log
maxretry = 6
bantime = 3600
[apache-overflows]
enabled = true
port = http,https
filter = apache-overflows
logpath = /var/log/apache2/*error.log
maxretry = 2
bantime = 3600
[ossec]
enabled = true
filter = ossec
logpath = /var/ossec/logs/alerts/alerts.log
maxretry = 1
bantime = 86400
port = all
protocol = all
banaction = iptables-allports
Create OSSEC filter for fail2ban
Create a custom filter that parses OSSEC alert logs to extract IP addresses for blocking.
[INCLUDES]
[Definition]
failregex = .\[\d+\]\s+\(\d+\).Src IP: .Rule: \d+ fired.Level: (?:1[0-5]|[6-9]).*
.\[\d+\]\s+\(\d+\).srcip: ;.rule: \d+; level: (?:1[0-5]|[6-9]);.
.\[\d+\]\s+\(\d+\).Attack Signature.Src IP: .
.\[\d+\]\s+\(\d+\).srcip: .rule: 100001.
.\[\d+\]\s+\(\d+\).srcip: .rule: 100002.
.\[\d+\]\s+\(\d+\).srcip: .rule: 100003.
.\[\d+\]\s+\(\d+\).srcip: .rule: 100004.
ignoreregex =
[Init]
journealmatch = _SYSTEMD_UNIT=ossec.service
Configure OSSEC active response integration
Create a custom active response script that interfaces with fail2ban for coordinated blocking.
#!/bin/bash
fail2ban-ban.sh - OSSEC active response script for fail2ban integration
Author: Binadit Infrastructure Team
LOGFILE="/var/ossec/logs/active-responses.log"
FAIL2BAN_CLIENT="/usr/bin/fail2ban-client"
Function to log messages
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - fail2ban-ban.sh: $1" >> $LOGFILE
}
Read the action and IP from OSSEC
read ACTION
read USER
read IP
read ALERTID
read RULEID
read AGENT
read FILENAME
Extract the IP address if it's in CIDR format
IP=$(echo $IP | cut -d'/' -f1)
Validate IP address
if [[ ! $IP =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
log "Invalid IP address: $IP"
exit 1
fi
Skip private IP addresses
if [[ $IP =~ ^10\. ]] || [[ $IP =~ ^172\.(1[6-9]|2[0-9]|3[0-1])\. ]] || [[ $IP =~ ^192\.168\. ]]; then
log "Skipping private IP: $IP"
exit 0
fi
case $ACTION in
add)
log "Banning IP $IP (Rule ID: $RULEID)"
# Ban the IP using fail2ban
$FAIL2BAN_CLIENT set ossec banip $IP
if [ $? -eq 0 ]; then
log "Successfully banned IP $IP"
else
log "Failed to ban IP $IP"
fi
;;
delete)
log "Unbanning IP $IP (Rule ID: $RULEID)"
# Unban the IP using fail2ban
$FAIL2BAN_CLIENT set ossec unbanip $IP
if [ $? -eq 0 ]; then
log "Successfully unbanned IP $IP"
else
log "Failed to unban IP $IP"
fi
;;
*)
log "Unknown action: $ACTION"
;;
esac
exit 0
Set permissions for active response script
Set proper permissions for the active response script so OSSEC can execute it.
sudo chmod 750 /var/ossec/active-response/bin/fail2ban-ban.sh
sudo chown root:ossec /var/ossec/active-response/bin/fail2ban-ban.sh
Add active response configuration to OSSEC
Configure OSSEC to use the custom active response script for high-level alerts.
fail2ban-ban
fail2ban-ban.sh
srcip
yes
fail2ban-ban
local
10
3600
Start and enable services
Enable and start both OSSEC and fail2ban services to begin monitoring.
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
sudo /var/ossec/bin/ossec-control start
sudo systemctl status fail2ban
Configure log monitoring integration
Set up centralized logging to ensure both systems can access and monitor the same log files effectively. This configuration was referenced in our centralized logging tutorial.
# OSSEC log integration
Send OSSEC alerts to a separate log file
if $programname startswith 'ossec' then /var/log/ossec-alerts.log
& stop
Ensure fail2ban can read OSSEC logs
$FileCreateMode 0644
$DirCreateMode 0755
Restart rsyslog service
Restart rsyslog to apply the new logging configuration.
sudo systemctl restart rsyslog
Configure automated threat response
Set up email notifications
Configure email alerts for both OSSEC and fail2ban to notify administrators of security events.
[Definition]
actionstart = printf %%b "Subject: [Fail2ban] : started on
Date: LC_ALL=C date +'%%a, %%d %%h %%Y %%T %%z'
From:
To:
Hi,
The jail has been started successfully.
Regards,
Fail2ban" | /usr/sbin/sendmail -f
actionstop = printf %%b "Subject: [Fail2ban] : stopped on
Date: LC_ALL=C date +'%%a, %%d %%h %%Y %%T %%z'
From:
To:
Hi,
The jail has been stopped.
Regards,
Fail2ban" | /usr/sbin/sendmail -f
actionban = printf %%b "Subject: [Fail2ban] : banned from
Date: LC_ALL=C date +'%%a, %%d %%h %%Y %%T %%z'
From:
To:
Hi,
The IP has just been banned by Fail2ban after
attempts against .
Here is more information about :
/usr/bin/whois || echo "Whois lookup failed"
Regards,
Fail2ban" | /usr/sbin/sendmail -f
actionunban = printf %%b "Subject: [Fail2ban] : unbanned from
Date: LC_ALL=C date +'%%a, %%d %%h %%Y %%T %%z'
From:
To:
Hi,
The IP has just been unbanned by Fail2ban.
Regards,
Fail2ban" | /usr/sbin/sendmail -f
Create monitoring dashboard script
Create a script to monitor the status of both systems and generate periodic reports.
#!/bin/bash
security-monitor.sh - Monitor OSSEC and fail2ban status
Author: Binadit Infrastructure Team
LOGFILE="/var/log/security-monitor.log"
EMAIL="admin@example.com"
Function to log messages
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a $LOGFILE
}
Check OSSEC status
check_ossec() {
if pgrep -f "ossec-syscheckd" > /dev/null; then
log "OSSEC: Running"
# Get recent alerts count
RECENT_ALERTS=$(tail -n 100 /var/ossec/logs/alerts/alerts.log | grep "$(date '+%Y %b %d')" | wc -l)
log "OSSEC: $RECENT_ALERTS alerts today"
else
log "OSSEC: Not running - ALERT!"
echo "OSSEC service is down on $(hostname)" | mail -s "OSSEC Alert" $EMAIL
fi
}
Check fail2ban status
check_fail2ban() {
if systemctl is-active --quiet fail2ban; then
log "Fail2ban: Running"
# Get banned IPs count
BANNED_IPS=$(/usr/bin/fail2ban-client status | grep "Currently banned" | awk '{print $4}')
log "Fail2ban: $BANNED_IPS IPs currently banned"
# List active jails
ACTIVE_JAILS=$(/usr/bin/fail2ban-client status | grep "Jail list" | cut -d: -f2 | xargs)
log "Fail2ban: Active jails: $ACTIVE_JAILS"
else
log "Fail2ban: Not running - ALERT!"
echo "Fail2ban service is down on $(hostname)" | mail -s "Fail2ban Alert" $EMAIL
fi
}
Check disk space for logs
check_disk_space() {
DISK_USAGE=$(df /var/log | tail -1 | awk '{print $5}' | sed 's/%//')
if [ $DISK_USAGE -gt 80 ]; then
log "Disk space warning: /var/log is ${DISK_USAGE}% full"
echo "Log partition is ${DISK_USAGE}% full on $(hostname)" | mail -s "Disk Space Alert" $EMAIL
else
log "Disk space: /var/log is ${DISK_USAGE}% full"
fi
}
Main monitoring function
main() {
log "=== Security Monitor Report ==="
check_ossec
check_fail2ban
check_disk_space
log "=== End Report ==="
echo "" >> $LOGFILE
}
main
Set up monitoring script permissions and cron job
Make the monitoring script executable and schedule it to run every hour.
sudo chmod 755 /usr/local/bin/security-monitor.sh
sudo chown root:root /usr/local/bin/security-monitor.sh
Add cron job for hourly monitoring
echo "0 /usr/local/bin/security-monitor.sh" | sudo crontab -
Set up automated threat response and monitoring
Configure automated response escalation
Set up different response levels based on threat severity and implement escalation policies.
fail2ban-ban
local
10
3600
fail2ban-ban
local
12
86400
fail2ban-ban
local
15
604800
Create threat intelligence integration
Set up a script that cross-references detected IPs with threat intelligence feeds for enhanced detection. You can extend this further using techniques from our OSSEC active response tutorial.
#!/bin/bash
threat-intel.sh - Threat intelligence integration for OSSEC and fail2ban
Author: Binadit Infrastructure Team
THREAT_DB="/var/ossec/threat-intelligence.db"
LOGFILE="/var/log/threat-intel.log"
ALERT_EMAIL="admin@example.com"
Function to log messages
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a $LOGFILE
}
Check if IP is in known threat lists
check_threat_intel() {
local IP=$1
local THREAT_FOUND=0
# Check against AbuseIPDB (requires API key)
if [ -n "$ABUSEIPDB_API_KEY" ]; then
ABUSE_RESULT=$(curl -s -H "Key: $ABUSEIPDB_API_KEY" \
"https://api.abuseipdb.com/api/v2/check?ipAddress=$IP&maxAgeInDays=90" | \
jq -r '.data.abuseConfidencePercentage')
if [ "$ABUSE_RESULT" != "null" ] && [ "$ABUSE_RESULT" -gt 50 ]; then
log "Threat detected: $IP has $ABUSE_RESULT% abuse confidence"
THREAT_FOUND=1
fi
fi
# Check local blacklist
if grep -q "$IP" "$THREAT_DB" 2>/dev/null; then
log "Threat detected: $IP found in local threat database"
THREAT_FOUND=1
fi
return $THREAT_FOUND
}
Process OSSEC alerts for threat intelligence
process_alerts() {
# Monitor OSSEC alerts log for new IPs
tail -f /var/ossec/logs/alerts/alerts.log | while read -r line; do
if echo "$line" | grep -q "Src IP:"; then
IP=$(echo "$line" | grep -o 'Src IP: [0-9.]*' | cut -d' ' -f3)
if [ -n "$IP" ]; then
if check_threat_intel "$IP"; then
log "High-priority threat detected from $IP"
# Immediately ban high-threat IPs
/usr/bin/fail2ban-client set ossec banip "$IP"
# Send alert email
echo "High-priority threat detected: $IP" | \
mail -s "Critical Security Alert" "$ALERT_EMAIL"
fi
fi
fi
done
}
Update threat intelligence database
update_threat_db() {
log "Updating threat intelligence database"
# Download threat feeds (example sources)
curl -s "https://raw.githubusercontent.com/stamparm/ipsum/master/levels/3.txt" > "$THREAT_DB.tmp"
if [ -s "$THREAT_DB.tmp" ]; then
mv "$THREAT_DB.tmp" "$THREAT_DB"
log "Threat database updated with $(wc -l < $THREAT_DB) entries"
else
log "Failed to update threat database"
rm -f "$THREAT_DB.tmp"
fi
}
case "$1" in
process)
process_alerts
;;
update)
update_threat_db
;;
check)
if [ -n "$2" ]; then
check_threat_intel "$2"
else
echo "Usage: $0 check "
fi
;;
*)
echo "Usage: $0 {process|update|check}"
;;
esac
Set up automated reporting
Create a comprehensive reporting system that generates daily security summaries.
#!/bin/bash
security-report.sh - Generate daily security reports
Author: Binadit Infrastructure Team
REPORT_EMAIL="admin@example.com"
REPORT_DATE=$(date '+%Y-%m-%d')
REPORT_FILE="/tmp/security-report-$REPORT_DATE.txt"
Generate comprehensive security report
generate_report() {
cat > "$REPORT_FILE" << EOF
Daily Security Report for $(hostname)
Generated: $(date '+%Y-%m-%d %H:%M:%S')
=== OSSEC Statistics ===
OSSEC Service Status: $(systemctl is-active ossec.service 2>/dev/null || echo "Unknown")
Alerts Today: $(grep "$(date '+%Y %b %d')" /var/ossec/logs/alerts/alerts.log 2>/dev/null | wc -l)
High Priority Alerts (Level 10+): $(grep "$(date '+%Y %b %d')" /var/ossec/logs/alerts/alerts.log 2>/dev/null | grep -E 'Rule: [0-9]+ \(level 1[0-5]\)' | wc -l)
Top Alert Rules Today:
$(grep "$(date '+%Y %b %d')" /var/ossec/logs/alerts/alerts.log 2>/dev/null | grep -o 'Rule: [0-9]*' | sort | uniq -c | sort -rn | head -5)
=== Fail2ban Statistics ===
Fail2ban Service Status: $(systemctl is-active fail2ban 2>/dev/null || echo "Unknown")
Active Jails: $(/usr/bin/fail2ban-client status 2>/dev/null | grep "Jail list" | cut -d: -f2 | xargs || echo "Unknown")
Currently Banned IPs: $(/usr/bin/fail2ban-client status 2>/dev/null | grep "Currently banned" | awk '{print $4}' || echo "0")
Banned IPs Today:
$(/usr/bin/fail2ban-client status 2>/dev/null | grep "Jail list" | cut -d: -f2 | xargs -n1 /usr/bin/fail2ban-client status | grep "Currently banned" || echo "None")
=== System Health ===
Disk Usage (/var/log): $(df -h /var/log | tail -1 | awk '{print $5}')
Memory Usage: $(free | grep Mem | awk '{printf "%.1f%%", $3/$2 * 100.0}')
Load Average: $(uptime | awk '{print $10" "$11" "$12}')
=== Log File Sizes ===
OSSEC Alerts: $(ls -lh /var/ossec/logs/alerts/alerts.log 2>/dev/null | awk '{print $5}' || echo "N/A")
Fail2ban Log: $(ls -lh /var/log/fail2ban.log 2>/dev/null | awk '{print $5}' || echo "N/A")
Auth Log: $(ls -lh /var/log/auth.log 2>/dev/null | awk '{print $5}' || echo "N/A")
=== Recent Critical Events ===
$(grep "$(date '+%Y %b %d')" /var/log/auth.log 2>/dev/null | grep -i "failed\|error\|invalid" | tail -10 || echo "No critical events found")
EOF
}
Send the report via email
send_report() {
if command -v mail >/dev/null 2>&1; then
mail -s "Daily Security Report - $(hostname) - $REPORT_DATE" "$REPORT_EMAIL" < "$REPORT_FILE"
echo "Security report sent to $REPORT_EMAIL"
else
echo "Mail command not available. Report saved to $REPORT_FILE"
fi
}
Main execution
generate_report
send_report
Cleanup
rm -f "$REPORT_FILE"
Schedule automated tasks
Set up cron jobs for automated monitoring, threat intelligence updates, and reporting.
sudo chmod 755 /usr/local/bin/threat-intel.sh
sudo chmod 755 /usr/local/bin/security-report.sh
Add cron jobs
sudo crontab -l > /tmp/current_cron
cat >> /tmp/current_cron << 'EOF'
Security monitoring tasks
0 /usr/local/bin/security-monitor.sh
0 6 * /usr/local/bin/threat-intel.sh update
0 8 * /usr/local/bin/security-report.sh
EOF
sudo crontab /tmp/current_cron
rm /tmp/current_cron
Verify your setup
Test the integration between OSSEC and fail2ban to ensure proper functionality.
# Check OSSEC status
sudo /var/ossec/bin/ossec-control status
Check fail2ban status
sudo systemctl status fail2ban
sudo fail2ban-client status
Test OSSEC alert generation
sudo /var/ossec/bin/ossec-logtest
Check active response logs
sudo tail -f /var/ossec/logs/active-responses.log
Check fail2ban logs
sudo tail -f /var/log/fail2ban.log
Test email notifications
echo "Test security alert" | mail -s "Test Alert" admin@example.com
Verify file permissions
ls -la /var/ossec/active-response/bin/fail2ban-ban.sh
ls -la /usr/local/bin/security-monitor.sh
To test the integration with controlled methods similar to our fail2ban testing approaches, you can trigger test alerts:
# Generate test SSH failed login (do this from a test machine)
This will trigger OSSEC rules and potentially fail2ban blocks
Monitor in real-time
sudo tail -f /var/ossec/logs/alerts/alerts.log &
sudo tail -f /var/log/fail2ban.log &
Check banned IPs
sudo fail2ban-client status ossec
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| OSSEC not starting | Configuration syntax error | sudo /var/ossec/bin/ossec-control enable debug and check logs |
| Fail2ban not banning IPs | Filter regex not matching logs | Test filter with fail2ban-regex /var/ossec/logs/alerts/alerts.log /etc/fail2ban/filter.d/ossec.conf |
| Active response not working | Script permissions or path issues | Check script permissions and test manually: sudo /var/ossec/active-response/bin/fail2ban-ban.sh |
| Email notifications not sent | Mail service not configured | Install and configure sendmail: sudo apt install sendmail |
| High false positive rate | Rules too sensitive | Adjust frequency and timeframe in custom rules and fail2ban maxretry settings |
| Log files growing too large | No log rotation configured | Configure logrotate for OSSEC and fail2ban logs |
Next steps
- Configure ModSecurity ML anomaly detection for web application security
- Set up ELK stack for centralized security log analysis and monitoring
- Configure OSSEC with Wazuh for advanced security monitoring
- Implement comprehensive network security policies with iptables
- Set up centralized security monitoring with ClamAV integration
Running this in production?
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Configuration
OSSEC_VERSION="3.7.0"
ADMIN_EMAIL="${1:-admin@example.com}"
SMTP_SERVER="${2:-localhost}"
# Usage
show_usage() {
echo "Usage: $0 [admin_email] [smtp_server]"
echo "Example: $0 admin@example.com localhost"
exit 1
}
# Logging functions
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# Cleanup on failure
cleanup() {
log_error "Installation failed. Cleaning up..."
systemctl stop ossec 2>/dev/null || true
systemctl stop fail2ban 2>/dev/null || true
rm -rf /tmp/ossec-hids-* 2>/dev/null || true
}
trap cleanup ERR
# Check prerequisites
check_prerequisites() {
if [[ $EUID -ne 0 ]]; then
log_error "This script must be run as root"
exit 1
fi
if [[ ! "$ADMIN_EMAIL" =~ ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$ ]]; then
log_error "Invalid email format"
show_usage
fi
}
# Detect distribution
detect_distro() {
if [[ ! -f /etc/os-release ]]; then
log_error "/etc/os-release not found. Cannot detect distribution."
exit 1
fi
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_UPDATE="apt update && apt upgrade -y"
PKG_INSTALL="apt install -y"
DEPS="build-essential gcc make unzip sendmail inotify-tools wget libevent-dev libssl-dev zlib1g-dev"
LOG_AUTH="/var/log/auth.log"
APACHE_ACCESS="/var/log/apache2/access.log"
APACHE_ERROR="/var/log/apache2/error.log"
;;
almalinux|rocky|centos|rhel|ol)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
DEPS="gcc gcc-c++ make unzip sendmail inotify-tools wget libevent-devel openssl-devel zlib-devel"
LOG_AUTH="/var/log/secure"
APACHE_ACCESS="/var/log/httpd/access_log"
APACHE_ERROR="/var/log/httpd/error_log"
# Enable EPEL for fail2ban
dnf install -y epel-release 2>/dev/null || true
;;
fedora)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
DEPS="gcc gcc-c++ make unzip sendmail inotify-tools wget libevent-devel openssl-devel zlib-devel"
LOG_AUTH="/var/log/secure"
APACHE_ACCESS="/var/log/httpd/access_log"
APACHE_ERROR="/var/log/httpd/error_log"
;;
amzn)
PKG_MGR="yum"
PKG_UPDATE="yum update -y"
PKG_INSTALL="yum install -y"
DEPS="gcc gcc-c++ make unzip sendmail inotify-tools wget libevent-devel openssl-devel zlib-devel"
LOG_AUTH="/var/log/secure"
APACHE_ACCESS="/var/log/httpd/access_log"
APACHE_ERROR="/var/log/httpd/error_log"
amazon-linux-extras install epel -y 2>/dev/null || true
;;
*)
log_error "Unsupported distribution: $ID"
exit 1
;;
esac
log_info "Detected distribution: $PRETTY_NAME"
}
# Create OSSEC configuration
create_ossec_config() {
cat > /var/ossec/etc/ossec.conf << 'EOF'
<ossec_config>
<global>
<email_notification>yes</email_notification>
<smtp_server>SMTP_SERVER_PLACEHOLDER</smtp_server>
<email_from>ossec@example.com</email_from>
<email_to>ADMIN_EMAIL_PLACEHOLDER</email_to>
<logall>yes</logall>
<logall_json>no</logall_json>
</global>
<rules>
<include>rules_config.xml</include>
<include>pam_rules.xml</include>
<include>sshd_rules.xml</include>
<include>syslog_rules.xml</include>
<include>apache_rules.xml</include>
<include>web_rules.xml</include>
<include>web_appsec_rules.xml</include>
<include>mysql_rules.xml</include>
<include>postfix_rules.xml</include>
<include>firewall_rules.xml</include>
<include>attack_rules.xml</include>
<include>ossec_rules.xml</include>
<include>local_rules.xml</include>
</rules>
<syscheck>
<frequency>79200</frequency>
<directories check_all="yes">/etc,/usr/bin,/usr/sbin</directories>
<directories check_all="yes">/bin,/sbin,/boot</directories>
<ignore>/etc/mtab</ignore>
<ignore>/etc/hosts.deny</ignore>
<ignore>/etc/adjtime</ignore>
<ignore>/etc/random-seed</ignore>
</syscheck>
<rootcheck>
<rootkit_files>/var/ossec/etc/shared/rootkit_files.txt</rootkit_files>
<rootkit_trojans>/var/ossec/etc/shared/rootkit_trojans.txt</rootkit_trojans>
<system_audit>/var/ossec/etc/shared/system_audit_rcl.txt</system_audit>
<system_audit>/var/ossec/etc/shared/cis_debian_linux_rcl.txt</system_audit>
</rootcheck>
<localfile>
<log_format>syslog</log_format>
<location>/var/log/messages</location>
</localfile>
<localfile>
<log_format>syslog</log_format>
<location>LOG_AUTH_PLACEHOLDER</location>
</localfile>
<localfile>
<log_format>apache</log_format>
<location>APACHE_ACCESS_PLACEHOLDER</location>
</localfile>
<localfile>
<log_format>apache</log_format>
<location>APACHE_ERROR_PLACEHOLDER</location>
</localfile>
<active-response>
<disabled>no</disabled>
</active-response>
</ossec_config>
EOF
sed -i "s/SMTP_SERVER_PLACEHOLDER/$SMTP_SERVER/g" /var/ossec/etc/ossec.conf
sed -i "s/ADMIN_EMAIL_PLACEHOLDER/$ADMIN_EMAIL/g" /var/ossec/etc/ossec.conf
sed -i "s|LOG_AUTH_PLACEHOLDER|$LOG_AUTH|g" /var/ossec/etc/ossec.conf
sed -i "s|APACHE_ACCESS_PLACEHOLDER|$APACHE_ACCESS|g" /var/ossec/etc/ossec.conf
sed -i "s|APACHE_ERROR_PLACEHOLDER|$APACHE_ERROR|g" /var/ossec/etc/ossec.conf
chown root:ossec /var/ossec/etc/ossec.conf
chmod 644 /var/ossec/etc/ossec.conf
}
# Create fail2ban jail configuration
create_fail2ban_config() {
cat > /etc/fail2ban/jail.local << EOF
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
backend = auto
[sshd]
enabled = true
port = ssh
logpath = $LOG_AUTH
maxretry = 3
[ossec-ssh]
enabled = true
filter = ossec-ssh
logpath = /var/ossec/logs/alerts/alerts.log
maxretry = 1
bantime = 86400
[ossec-web]
enabled = true
filter = ossec-web
logpath = /var/ossec/logs/alerts/alerts.log
maxretry = 1
bantime = 86400
EOF
# Create OSSEC filters for fail2ban
mkdir -p /etc/fail2ban/filter.d
cat > /etc/fail2ban/filter.d/ossec-ssh.conf << 'EOF'
[Definition]
failregex = .*\s+<.*>\s+<.*>\s+<.*>\s+(authentication_failed|Invalid_user|Connection_closed|Multiple_authentication_failures).*Src IP: <HOST>
ignoreregex =
EOF
cat > /etc/fail2ban/filter.d/ossec-web.conf << 'EOF'
[Definition]
failregex = .*\s+<.*>\s+<.*>\s+<.*>\s+(Web_server_400_error|Web_server_403_error|Web_server_404_error|Multiple_web_server_400_errors).*Src IP: <HOST>
ignoreregex =
EOF
chmod 644 /etc/fail2ban/jail.local /etc/fail2ban/filter.d/ossec-*.conf
}
# Main installation
main() {
log_info "Starting OSSEC and fail2ban installation"
echo "[1/10] Checking prerequisites..."
check_prerequisites
echo "[2/10] Detecting distribution..."
detect_distro
echo "[3/10] Updating system packages..."
$PKG_UPDATE
echo "[4/10] Installing OSSEC dependencies..."
$PKG_INSTALL $DEPS
echo "[5/10] Downloading OSSEC..."
cd /tmp
wget -q "https://github.com/ossec/ossec-hids/archive/v${OSSEC_VERSION}.tar.gz"
tar -xzf "v${OSSEC_VERSION}.tar.gz"
cd "ossec-hids-${OSSEC_VERSION}"
echo "[6/10] Installing OSSEC..."
# Automated installation answers
echo -e "\nen\n\nlocal\n\ny\n$ADMIN_EMAIL\n$SMTP_SERVER\ny\ny\ny\ny\n\n" | ./install.sh
echo "[7/10] Configuring OSSEC..."
create_ossec_config
echo "[8/10] Installing fail2ban..."
$PKG_INSTALL fail2ban
echo "[9/10] Configuring fail2ban integration..."
create_fail2ban_config
echo "[10/10] Starting services..."
systemctl enable ossec
systemctl start ossec
systemctl enable fail2ban
systemctl start fail2ban
# Verification
sleep 5
if systemctl is-active --quiet ossec && systemctl is-active --quiet fail2ban; then
log_info "Installation completed successfully!"
log_info "OSSEC Web UI: http://$(hostname -I | awk '{print $1}'):1515"
log_info "Configuration files:"
log_info " - OSSEC: /var/ossec/etc/ossec.conf"
log_info " - fail2ban: /etc/fail2ban/jail.local"
log_info " - Logs: /var/ossec/logs/ and /var/log/fail2ban.log"
else
log_error "Service verification failed"
exit 1
fi
}
main "$@"
Review the script before running. Execute with: bash install.sh