Configure HAProxy with ModSecurity 3 using SPOE protocol to create a high-performance web application firewall that protects against OWASP Top 10 threats while maintaining load balancing capabilities.
Prerequisites
- Root access to server
- HAProxy already installed
- Basic understanding of load balancing
- Familiarity with web application security
What this solves
Modern web applications require both load balancing and advanced threat protection. This tutorial shows you how to integrate ModSecurity 3 with HAProxy using the Stream Processing Offload Engine (SPOE) protocol to create a comprehensive WAF solution that filters malicious traffic before it reaches your backend servers.
Step-by-step configuration
Update system packages
Start by updating your package manager and installing required dependencies for compilation and security tools.
sudo apt update && sudo apt upgrade -y
sudo apt install -y build-essential git cmake libcurl4-openssl-dev libgeoip-dev libyajl-dev libxml2-dev libpcre2-dev libssl-dev zlib1g-dev pkg-config libmodsecurity3 libmodsecurity-dev haproxy
Install ModSecurity 3 SPOE agent
Clone and compile the ModSecurity SPOE agent that will handle WAF processing for HAProxy requests.
cd /opt
sudo git clone https://github.com/haproxy/spoe-modsecurity.git
cd spoe-modsecurity
sudo mkdir build && cd build
sudo cmake ..
sudo make -j$(nproc)
sudo make install
Download OWASP Core Rule Set
Install the OWASP Core Rule Set which provides protection against the OWASP Top 10 security risks and other common attack vectors.
sudo mkdir -p /etc/modsecurity
cd /etc/modsecurity
sudo git clone https://github.com/coreruleset/coreruleset.git
sudo cp coreruleset/crs-setup.conf.example coreruleset/crs-setup.conf
Configure ModSecurity main configuration
Create the main ModSecurity configuration file with recommended security settings and logging options.
SecRuleEngine On
SecRequestBodyAccess On
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072
SecRequestBodyLimitAction Reject
SecRequestBodyInMemoryLimit 131072
SecResponseBodyAccess On
SecResponseBodyMimeType text/plain text/html text/xml
SecResponseBodyLimit 524288
SecResponseBodyLimitAction ProcessPartial
SecTmpDir /tmp/
SecDataDir /tmp/
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABIJDEFHZ
SecAuditLogType Serial
SecAuditLog /var/log/modsecurity/audit.log
SecArgumentSeparator &
SecCookieFormat 0
SecUnicodeMapFile unicode.mapping 20127
SecStatusEngine On
Create OWASP CRS configuration
Configure the Core Rule Set with custom paranoia level and exclusions for your application.
SecDefaultAction "phase:1,log,auditlog,pass"
SecDefaultAction "phase:2,log,auditlog,pass"
Set paranoia level (1-4, higher = more strict)
SecAction "id:900000,phase:1,nolog,pass,t:none,setvar:tx.paranoia_level=2"
Inbound and Outbound Anomaly Score Threshold
SecAction "id:900110,phase:1,nolog,pass,t:none,setvar:tx.inbound_anomaly_score_threshold=5"
SecAction "id:900111,phase:1,nolog,pass,t:none,setvar:tx.outbound_anomaly_score_threshold=4"
Application specific exclusions
Exclude SQL keywords in legitimate application data
SecRuleRemoveById 942100
Create ModSecurity rules include file
Create a master rules file that includes all OWASP CRS rules and custom configurations.
Include /etc/modsecurity/modsecurity.conf
Include /etc/modsecurity/coreruleset/crs-setup.conf
Include /etc/modsecurity/coreruleset/rules/*.conf
Configure SPOE agent configuration
Create the SPOE agent configuration that defines how ModSecurity processes requests from HAProxy.
[modsecurity]
spoe-agent modsecurity-agent
messages check-request
option var-prefix modsec
timeout hello 10s
timeout idle 30s
timeout processing 15s
use-backend spoe-modsecurity
spoe-message check-request
args unique-id method path query body
event on-frontend-http-request
backend spoe-modsecurity
mode tcp
timeout connect 5s
timeout server 30s
server modsec-spoe1 127.0.0.1:12345
Configure HAProxy with SPOE integration
Update HAProxy configuration to load the SPOE filter and process requests through ModSecurity before forwarding to backends.
global
daemon
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
# SSL Configuration
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
option httplog
option dontlognull
frontend web_frontend
bind *:80
bind *:443 ssl crt /etc/ssl/certs/server.pem
# Enable SPOE filter
filter spoe engine modsecurity config /etc/haproxy/spoe-modsecurity.conf
# Process ModSecurity response
http-request lua.modsecurity-process-request
# Block if ModSecurity detected threats
http-request deny if { var(txn.modsec.code) -m int gt 0 }
# Redirect HTTP to HTTPS
http-request redirect scheme https unless { ssl_fc }
default_backend web_servers
backend web_servers
balance roundrobin
option httpchk GET /health
server web1 192.168.1.10:80 check
server web2 192.168.1.11:80 check
server web3 192.168.1.12:80 check
listen stats
bind *:8404
stats enable
stats uri /stats
stats refresh 30s
stats admin if TRUE
Create ModSecurity SPOE service configuration
Create a systemd service file to manage the ModSecurity SPOE agent daemon.
[Unit]
Description=ModSecurity SPOE Agent
After=network.target
Requires=network.target
[Service]
Type=simple
User=haproxy
Group=haproxy
ExecStart=/usr/local/bin/spoe-modsecurity -f /etc/modsecurity/main.conf
Restart=always
RestartSec=10
KillMode=mixed
KillSignal=SIGTERM
TimeoutStopSec=5
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
NoNewPrivileges=true
ReadWritePaths=/tmp /var/log/modsecurity
[Install]
WantedBy=multi-user.target
Create log directories with proper permissions
Set up logging directories with correct ownership and permissions for security and functionality.
sudo mkdir -p /var/log/modsecurity
sudo chown haproxy:haproxy /var/log/modsecurity
sudo chmod 755 /var/log/modsecurity
Configure logrotate for ModSecurity logs
Set up log rotation to prevent ModSecurity audit logs from consuming excessive disk space.
/var/log/modsecurity/*.log {
daily
missingok
rotate 52
compress
delaycompress
notifempty
create 644 haproxy haproxy
postrotate
systemctl reload rsyslog > /dev/null 2>&1 || true
endscript
}
Start and enable services
Enable and start both the ModSecurity SPOE agent and HAProxy with the new configuration.
sudo systemctl daemon-reload
sudo systemctl enable modsecurity-spoe
sudo systemctl start modsecurity-spoe
sudo systemctl restart haproxy
sudo systemctl status modsecurity-spoe
sudo systemctl status haproxy
Configure custom WAF rules
Create application-specific rules
Add custom ModSecurity rules for your specific application requirements and threat landscape.
# Block common attack patterns
SecRule ARGS "@detectSQLi" \
"id:1001,phase:2,block,msg:'SQL Injection Attack Detected',logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',severity:2,tag:'attack-sqli'"
Rate limiting rule
SecRule IP:bf_counter "@gt 20" \
"id:1002,phase:1,deny,status:429,msg:'Rate limit exceeded',expirevar:ip.bf_counter=60"
Block suspicious user agents
SecRule REQUEST_HEADERS:User-Agent "@pmFromFile /etc/modsecurity/bad-user-agents.txt" \
"id:1003,phase:1,deny,msg:'Suspicious User Agent Blocked'"
Geographic blocking (requires GeoIP)
SecRule GEO:COUNTRY_CODE "@pmFromFile /etc/modsecurity/blocked-countries.txt" \
"id:1004,phase:1,deny,msg:'Request from blocked country'"
Create threat intelligence feeds
Set up files for maintaining lists of malicious IPs, user agents, and other threat indicators.
sudo cat > /etc/modsecurity/bad-user-agents.txt << 'EOF'
sqlmap
nmap
niktowget
curl/7.0
EOF
sudo cat > /etc/modsecurity/blocked-countries.txt << 'EOF'
CN
RU
KP
EOF
Include custom rules in main configuration
Update the main ModSecurity configuration to include your custom rules and threat intelligence.
sudo echo "Include /etc/modsecurity/custom-rules.conf" >> /etc/modsecurity/main.conf
sudo systemctl restart modsecurity-spoe
Monitor and tune WAF performance
Set up performance monitoring
Create monitoring scripts to track ModSecurity performance impact and detection statistics.
#!/bin/bash
LOG_FILE="/var/log/modsecurity/audit.log"
STATS_FILE="/var/log/modsecurity/daily-stats.log"
DATE=$(date +%Y-%m-%d)
BLOCKED=$(grep -c "\[id \"" $LOG_FILE 2>/dev/null || echo 0)
SQL_INJECTION=$(grep -c "attack-sqli" $LOG_FILE 2>/dev/null || echo 0)
XSS_ATTACKS=$(grep -c "attack-xss" $LOG_FILE 2>/dev/null || echo 0)
RCE_ATTACKS=$(grep -c "attack-rce" $LOG_FILE 2>/dev/null || echo 0)
echo "$DATE: Total blocked: $BLOCKED, SQLi: $SQL_INJECTION, XSS: $XSS_ATTACKS, RCE: $RCE_ATTACKS" >> $STATS_FILE
Reset daily log
echo "" > $LOG_FILE
Create performance tuning configuration
Optimize ModSecurity settings for your traffic volume and performance requirements.
# Performance optimizations
SecRequestBodyInMemoryLimit 262144
SecRequestBodyNoFilesLimit 262144
SecResponseBodyLimit 1048576
Disable response body inspection for static content
SecRule REQUEST_FILENAME "@endsWith .css" "id:2001,phase:2,pass,nolog,ctl:responseBodyAccess=off"
SecRule REQUEST_FILENAME "@endsWith .js" "id:2002,phase:2,pass,nolog,ctl:responseBodyAccess=off"
SecRule REQUEST_FILENAME "@endsWith .png" "id:2003,phase:2,pass,nolog,ctl:responseBodyAccess=off"
SecRule REQUEST_FILENAME "@endsWith .jpg" "id:2004,phase:2,pass,nolog,ctl:responseBodyAccess=off"
Skip processing for known good sources
SecRule REMOTE_ADDR "@ipMatchFromFile /etc/modsecurity/whitelist-ips.txt" "id:2005,phase:1,pass,nolog,ctl:ruleEngine=off"
Set up automated rule updates
Create a script to automatically update OWASP Core Rule Set to the latest version.
#!/bin/bash
cd /etc/modsecurity/
git -C coreruleset pull origin master
Test configuration
if /usr/local/bin/spoe-modsecurity -t -f /etc/modsecurity/main.conf; then
systemctl restart modsecurity-spoe
echo "$(date): OWASP rules updated successfully" >> /var/log/modsecurity/updates.log
else
git -C coreruleset reset --hard HEAD~1
echo "$(date): OWASP rules update failed, rolled back" >> /var/log/modsecurity/updates.log
fi
Schedule automated monitoring and updates
Set up cron jobs for daily statistics collection and weekly rule updates.
sudo chmod +x /usr/local/bin/modsecurity-stats.sh
sudo chmod +x /usr/local/bin/update-owasp-rules.sh
sudo crontab -e
Add these lines:
Daily stats collection
0 1 * /usr/local/bin/modsecurity-stats.sh
Weekly rule updates
0 2 0 /usr/local/bin/update-owasp-rules.sh
Test WAF functionality
Test SQL injection protection
Verify that ModSecurity detects and blocks common SQL injection attempts.
# Test basic SQL injection
curl -X POST "http://example.com/login" -d "username=admin' OR '1'='1&password=test"
Test advanced SQL injection
curl "http://example.com/search?q=1' UNION SELECT * FROM users--"
Check logs for detection
sudo grep -i "sql injection" /var/log/modsecurity/audit.log
Test cross-site scripting protection
Verify XSS attack detection and blocking capabilities.
# Test reflected XSS
curl "http://example.com/search?q="
Test stored XSS attempt
curl -X POST "http://example.com/comment" -d "message="
Check detection logs
sudo grep -i "xss" /var/log/modsecurity/audit.log
Test rate limiting functionality
Verify that rate limiting rules are working correctly to prevent brute force attacks.
# Generate multiple requests to trigger rate limiting
for i in {1..25}; do
curl "http://example.com/login" -d "username=admin&password=wrong" &
done
wait
Check if rate limiting was triggered
sudo grep -i "rate limit" /var/log/modsecurity/audit.log
Verify your setup
# Check service status
sudo systemctl status haproxy
sudo systemctl status modsecurity-spoe
Verify SPOE connection
ss -tlnp | grep :12345
Test configuration syntax
sudo haproxy -f /etc/haproxy/haproxy.cfg -c
/usr/local/bin/spoe-modsecurity -t -f /etc/modsecurity/main.conf
Check recent blocked requests
sudo tail -n 50 /var/log/modsecurity/audit.log
Monitor real-time activity
sudo tail -f /var/log/haproxy.log
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| SPOE agent won't start | Missing ModSecurity library | sudo ldconfig and verify libmodsecurity3 installation |
| HAProxy can't connect to SPOE | SPOE agent not listening | Check ss -tlnp | grep 12345 and restart modsecurity-spoe |
| All requests blocked | Paranoia level too high | Reduce paranoia level in /etc/modsecurity/coreruleset/crs-setup.conf |
| High CPU usage | Response body inspection enabled | Disable for static content with ctl:responseBodyAccess=off |
| Permission denied on logs | Incorrect log directory ownership | sudo chown -R haproxy:haproxy /var/log/modsecurity |
| Rules not updating | Git authentication issues | Use HTTPS clone instead of SSH for OWASP repository |
Next steps
- Set up centralized logging with rsyslog and logrotate for security events
- Monitor HAProxy and Consul with Prometheus and Grafana dashboards
- Implement HAProxy rate limiting and DDoS protection with advanced security rules
- Integrate HAProxy WAF with threat intelligence feeds and automated blocking
- Configure HAProxy WAF geographic blocking with GeoIP databases
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Global variables
MODSEC_DIR="/etc/modsecurity"
SPOE_DIR="/opt/spoe-modsecurity"
LOG_DIR="/var/log/modsecurity"
# Usage
usage() {
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " -h, --help Show this help message"
echo " --paranoia-level LEVEL Set OWASP CRS paranoia level (1-4, default: 2)"
exit 1
}
# Error handling
cleanup() {
echo -e "${RED}[ERROR] Installation failed. Cleaning up...${NC}"
systemctl stop haproxy >/dev/null 2>&1 || true
rm -rf "${SPOE_DIR}" >/dev/null 2>&1 || true
exit 1
}
trap cleanup ERR
# Check if running as root
if [[ $EUID -ne 0 ]]; then
echo -e "${RED}This script must be run as root${NC}"
exit 1
fi
# Parse arguments
PARANOIA_LEVEL=2
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help) usage ;;
--paranoia-level) PARANOIA_LEVEL="$2"; shift 2 ;;
*) echo -e "${RED}Unknown option: $1${NC}"; usage ;;
esac
done
# Validate paranoia level
if [[ ! "$PARANOIA_LEVEL" =~ ^[1-4]$ ]]; then
echo -e "${RED}Paranoia level must be between 1-4${NC}"
exit 1
fi
# Auto-detect distribution
echo -e "${YELLOW}[1/10] Detecting system distribution...${NC}"
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_UPDATE="apt update && apt upgrade -y"
PKG_INSTALL="apt install -y"
BUILD_DEPS="build-essential git cmake libcurl4-openssl-dev libgeoip-dev libyajl-dev libxml2-dev libpcre2-dev libssl-dev zlib1g-dev pkg-config"
MODSEC_PKGS="libmodsecurity3 libmodsecurity-dev haproxy"
;;
almalinux|rocky|centos|rhel|ol)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
BUILD_DEPS="git cmake libcurl-devel GeoIP-devel yajl-devel libxml2-devel pcre2-devel openssl-devel zlib-devel pkgconfig"
MODSEC_PKGS="libmodsecurity libmodsecurity-devel haproxy"
dnf groupinstall -y "Development Tools" >/dev/null 2>&1 || true
;;
fedora)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
BUILD_DEPS="git cmake libcurl-devel GeoIP-devel yajl-devel libxml2-devel pcre2-devel openssl-devel zlib-devel pkgconfig"
MODSEC_PKGS="libmodsecurity libmodsecurity-devel haproxy"
dnf groupinstall -y "Development Tools" >/dev/null 2>&1 || true
;;
amzn)
PKG_MGR="yum"
PKG_UPDATE="yum update -y"
PKG_INSTALL="yum install -y"
BUILD_DEPS="git cmake libcurl-devel GeoIP-devel yajl-devel libxml2-devel pcre2-devel openssl-devel zlib-devel pkgconfig"
MODSEC_PKGS="libmodsecurity libmodsecurity-devel haproxy"
yum groupinstall -y "Development Tools" >/dev/null 2>&1 || true
;;
*) echo -e "${RED}Unsupported distribution: $ID${NC}"; exit 1 ;;
esac
else
echo -e "${RED}Cannot detect distribution${NC}"
exit 1
fi
echo -e "${GREEN}Detected: $PRETTY_NAME${NC}"
# Update system packages
echo -e "${YELLOW}[2/10] Updating system packages...${NC}"
eval "$PKG_UPDATE" >/dev/null
# Install dependencies
echo -e "${YELLOW}[3/10] Installing build dependencies...${NC}"
eval "$PKG_INSTALL $BUILD_DEPS $MODSEC_PKGS" >/dev/null
# Create directories
echo -e "${YELLOW}[4/10] Creating directory structure...${NC}"
mkdir -p "$LOG_DIR"
chown haproxy:haproxy "$LOG_DIR"
chmod 750 "$LOG_DIR"
mkdir -p "$MODSEC_DIR"
# Install ModSecurity SPOE agent
echo -e "${YELLOW}[5/10] Compiling ModSecurity SPOE agent...${NC}"
cd /opt
git clone -q https://github.com/haproxy/spoe-modsecurity.git
cd spoe-modsecurity
mkdir -p build && cd build
cmake .. >/dev/null
make -j$(nproc) >/dev/null
make install >/dev/null
# Download OWASP Core Rule Set
echo -e "${YELLOW}[6/10] Installing OWASP Core Rule Set...${NC}"
cd "$MODSEC_DIR"
git clone -q https://github.com/coreruleset/coreruleset.git
cp coreruleset/crs-setup.conf.example coreruleset/crs-setup.conf
chown -R root:root "$MODSEC_DIR"
chmod -R 644 "$MODSEC_DIR"/*
find "$MODSEC_DIR" -type d -exec chmod 755 {} \;
# Configure ModSecurity main configuration
echo -e "${YELLOW}[7/10] Creating ModSecurity configuration...${NC}"
cat > "$MODSEC_DIR/modsecurity.conf" << 'EOF'
SecRuleEngine On
SecRequestBodyAccess On
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072
SecRequestBodyLimitAction Reject
SecRequestBodyInMemoryLimit 131072
SecResponseBodyAccess On
SecResponseBodyMimeType text/plain text/html text/xml
SecResponseBodyLimit 524288
SecResponseBodyLimitAction ProcessPartial
SecTmpDir /tmp/
SecDataDir /tmp/
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABIJDEFHZ
SecAuditLogType Serial
SecAuditLog /var/log/modsecurity/audit.log
SecArgumentSeparator &
SecCookieFormat 0
SecUnicodeMapFile unicode.mapping 20127
SecStatusEngine On
EOF
# Create OWASP CRS configuration
cat > "$MODSEC_DIR/crs-custom.conf" << EOF
SecDefaultAction "phase:1,log,auditlog,pass"
SecDefaultAction "phase:2,log,auditlog,pass"
# Set paranoia level
SecAction "id:900000,phase:1,nolog,pass,t:none,setvar:tx.paranoia_level=${PARANOIA_LEVEL}"
# Inbound and Outbound Anomaly Score Threshold
SecAction "id:900110,phase:1,nolog,pass,t:none,setvar:tx.inbound_anomaly_score_threshold=5"
SecAction "id:900111,phase:1,nolog,pass,t:none,setvar:tx.outbound_anomaly_score_threshold=4"
# Application specific exclusions
SecRuleRemoveById 942100
EOF
# Create rules include file
cat > "$MODSEC_DIR/main.conf" << EOF
Include $MODSEC_DIR/modsecurity.conf
Include $MODSEC_DIR/crs-custom.conf
Include $MODSEC_DIR/coreruleset/crs-setup.conf
Include $MODSEC_DIR/coreruleset/rules/*.conf
EOF
# Set proper permissions
chmod 644 "$MODSEC_DIR"/*.conf
# Create SPOE configuration
echo -e "${YELLOW}[8/10] Configuring SPOE agent...${NC}"
cat > /etc/haproxy/spoe-modsecurity.conf << 'EOF'
[modsecurity]
spoe-agent modsecurity-agent
messages check-request
option var-prefix modsec
timeout hello 10s
timeout idle 30s
timeout processing 15s
use-backend spoe-modsecurity
spoe-message check-request
args unique-id method path query body
event on-frontend-http-request
backend spoe-modsecurity
mode tcp
timeout connect 5s
timeout server 30s
server modsec-spoe1 127.0.0.1:12345
EOF
chmod 644 /etc/haproxy/spoe-modsecurity.conf
# Create systemd service for SPOE agent
echo -e "${YELLOW}[9/10] Creating SPOE agent service...${NC}"
cat > /etc/systemd/system/modsecurity-spoe.service << EOF
[Unit]
Description=ModSecurity SPOE Agent
After=network.target
[Service]
Type=simple
User=haproxy
Group=haproxy
ExecStart=/usr/local/bin/spoe-modsecurity -f $MODSEC_DIR/main.conf -p 12345
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
# Enable and start service
systemctl daemon-reload
systemctl enable modsecurity-spoe.service
systemctl start modsecurity-spoe.service
# Configure HAProxy with SPOE
echo -e "${YELLOW}[10/10] Configuring HAProxy integration...${NC}"
if [ ! -f /etc/haproxy/haproxy.cfg.backup ]; then
cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.backup
fi
# Add SPOE filter to HAProxy configuration
cat >> /etc/haproxy/haproxy.cfg << 'EOF'
# ModSecurity SPOE Configuration
frontend web-frontend
bind *:80
filter spoe engine modsecurity config /etc/haproxy/spoe-modsecurity.conf
http-request deny if { var(txn.modsec.code) -m int gt 0 }
default_backend web-servers
backend web-servers
balance roundrobin
server web1 127.0.0.1:8080 check
EOF
# Restart services
systemctl restart haproxy
systemctl enable haproxy
# Verification
echo -e "${YELLOW}Performing verification checks...${NC}"
if systemctl is-active --quiet modsecurity-spoe.service; then
echo -e "${GREEN}✓ ModSecurity SPOE service is running${NC}"
else
echo -e "${RED}✗ ModSecurity SPOE service failed to start${NC}"
exit 1
fi
if systemctl is-active --quiet haproxy; then
echo -e "${GREEN}✓ HAProxy is running${NC}"
else
echo -e "${RED}✗ HAProxy failed to start${NC}"
exit 1
fi
if [ -f "$LOG_DIR/audit.log" ]; then
echo -e "${GREEN}✓ ModSecurity logging is configured${NC}"
else
echo -e "${YELLOW}! ModSecurity audit log will be created on first request${NC}"
fi
echo -e "${GREEN}"
echo "=================================="
echo "HAProxy WAF Installation Complete"
echo "=================================="
echo -e "${NC}"
echo "Configuration files:"
echo "- ModSecurity: $MODSEC_DIR/main.conf"
echo "- SPOE Config: /etc/haproxy/spoe-modsecurity.conf"
echo "- HAProxy: /etc/haproxy/haproxy.cfg"
echo "- Logs: $LOG_DIR/audit.log"
echo ""
echo "Service status:"
systemctl status modsecurity-spoe.service --no-pager -l
systemctl status haproxy --no-pager -l
echo ""
echo -e "${YELLOW}Next steps:${NC}"
echo "1. Configure your backend servers in HAProxy"
echo "2. Test WAF functionality with curl or web requests"
echo "3. Monitor logs in $LOG_DIR/"
echo "4. Customize OWASP CRS rules as needed"
Review the script before running. Execute with: bash install.sh