Implement OpenLiteSpeed WAF and DDoS protection with ModSecurity 3 and rate limiting

Intermediate 45 min Apr 27, 2026 134 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Set up comprehensive web application security for OpenLiteSpeed with ModSecurity 3 web application firewall, OWASP Core Rule Set for threat protection, and advanced rate limiting to defend against DDoS attacks and malicious traffic.

Prerequisites

  • Root access to server
  • OpenLiteSpeed web server
  • Basic understanding of web security concepts
  • Email configured for alerts

What this solves

OpenLiteSpeed provides excellent performance but needs additional security layers to protect against web application attacks and DDoS attempts. This tutorial implements ModSecurity 3 as a web application firewall (WAF) with the OWASP Core Rule Set, configures advanced rate limiting rules, and sets up security event monitoring to create a comprehensive defense system for your web applications.

Step-by-step installation

Update system packages

Start by updating your package manager to ensure you have the latest security patches and package information.

sudo apt update && sudo apt upgrade -y
sudo dnf update -y

Install OpenLiteSpeed and dependencies

Install OpenLiteSpeed web server along with the development tools and libraries needed for ModSecurity compilation.

wget -O - https://repo.litespeed.sh | sudo bash
sudo apt install -y openlitespeed lsphp82 lsphp82-mysql
sudo apt install -y build-essential libpcre3-dev zlib1g-dev libssl-dev libxml2-dev libpcre++-dev libgd-dev
sudo rpm -Uvh http://rpms.litespeedtech.com/centos/litespeed-repo-1.3-1.el8.noarch.rpm
sudo dnf install -y openlitespeed lsphp82 lsphp82-mysql
sudo dnf groupinstall -y "Development Tools"
sudo dnf install -y pcre-devel openssl-devel libxml2-devel gd-devel

Install ModSecurity 3 library

Download and compile ModSecurity 3 from source to get the latest security features and performance improvements.

cd /tmp
git clone https://github.com/SpiderLabs/ModSecurity.git
cd ModSecurity
git checkout v3.0.12
git submodule init
git submodule update

Configure and compile ModSecurity

Build ModSecurity with optimizations enabled and install it to the system directories.

./build.sh
./configure --enable-pcre-study --enable-pcre-jit
make -j$(nproc)
sudo make install
sudo ldconfig

Install ModSecurity connector for OpenLiteSpeed

Clone and build the ModSecurity connector that integrates with OpenLiteSpeed's module system.

cd /tmp
git clone https://github.com/SpiderLabs/ModSecurity-nginx.git
cd ModSecurity-nginx
git checkout v1.0.3

Download OWASP Core Rule Set

Install the OWASP Core Rule Set (CRS) which provides comprehensive protection against common web application attacks.

sudo mkdir -p /usr/local/modsecurity
cd /usr/local/modsecurity
sudo git clone https://github.com/coreruleset/coreruleset.git
sudo mv coreruleset/crs-setup.conf.example coreruleset/crs-setup.conf
sudo mv coreruleset/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example coreruleset/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
sudo mv coreruleset/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example coreruleset/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf

Create ModSecurity main configuration

Configure ModSecurity with security rules, logging, and performance settings tailored for production use.

# ModSecurity Configuration
SecRuleEngine On
SecRequestBodyAccess On
SecResponseBodyAccess Off
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072
SecRequestBodyLimitAction Reject
SecPcreMatchLimit 250000
SecPcreMatchLimitRecursion 250000

Audit Log Configuration

SecAuditEngine RelevantOnly SecAuditLogRelevantStatus "^(?:5|4(?!04))" SecAuditLogParts ABIJDEFHZ SecAuditLogType Serial SecAuditLog /var/log/openlitespeed/modsec_audit.log

Debug Log

SecDebugLog /var/log/openlitespeed/modsec_debug.log SecDebugLogLevel 3

Temporary file configuration

SecTmpDir /tmp/ SecDataDir /tmp/

Content-Type header configuration

SecRule REQUEST_HEADERS:Content-Type "^(?:application(?:/soap\+|/)|text/)xml" \ "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML" SecRule REQUEST_HEADERS:Content-Type "^application/json" \ "id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON" SecRule REQUEST_HEADERS:Content-Type "^application/x-www-form-urlencoded" \ "id:'200002',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=URLENCODED" SecRule REQUEST_HEADERS:Content-Type "^multipart/form-data" \ "id:'200003',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=MULTIPART"

Include OWASP Core Rule Set

Include /usr/local/modsecurity/coreruleset/crs-setup.conf Include /usr/local/modsecurity/coreruleset/rules/*.conf

Configure OpenLiteSpeed virtual host security

Create a secure virtual host configuration with ModSecurity integration and rate limiting rules.

docRoot                   /usr/local/lsws/Example/html/
vhDomain                  example.com
allowSymbolLink           1
enableScript              1
restrained                0
setUIDMode                0

Security Headers

extraHeaders { X-Frame-Options SAMEORIGIN X-Content-Type-Options nosniff X-XSS-Protection "1; mode=block" Referrer-Policy strict-origin-when-cross-origin Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';" }

Rate Limiting Configuration

accessControl { allow * }

Request Rate Limiting

requestLimitCtrl { staticReqPerSec 20 dynReqPerSec 10 outBandwidth 1024 inBandwidth 1024 }

Connection Limits

connectionCtrl { staticReqPerSec 50 dynReqPerSec 25 reqRate 0 reqUnit 1 outBandwidth 0 inBandwidth 0 }

ModSecurity Configuration

moduleEnabled { cache 0 esi 0 expires 1 headers 1 uploadprogress 0 modsecurity 1 } moduleSecurityConf { modsec_rules /usr/local/modsecurity/modsecurity.conf modsec_rules_remote 0 modsec_rules_timeout 5 } scripthandler { add lsphp82 php } phpIniOverride { php_value upload_max_filesize 32M php_value post_max_size 32M php_value max_execution_time 300 php_value max_input_vars 3000 }

Configure advanced rate limiting rules

Create comprehensive rate limiting and DDoS protection rules that block aggressive behavior while allowing legitimate traffic.

# Global Rate Limiting Configuration
requestLimitCtrl {
  staticReqPerSec         100
  dynReqPerSec            50
  outBandwidth            10240
  inBandwidth             10240
}

Connection Control

connectionCtrl { maxConnections 2000 maxSSLConnections 1000 connTimeout 300 maxKeepAliveReq 1000 keepAliveTimeout 5 sndBufSize 0 rcvBufSize 0 }

Anti-DDoS Configuration

perClientConnLimit { staticReqPerSec 20 dynReqPerSec 10 outBandwidth 1024 inBandwidth 1024 softLimit 500 hardLimit 600 gracePeriod 15 banPeriod 300 }

IP-based Throttling

accounting { staticReqPerSec 50 dynReqPerSec 25 outBandwidth 5120 inBandwidth 2048 reqRate 20 reqUnit 1 respBuffer 0 }

Request Filtering

requestFilter { enableCtxControl 1 ctxTimeout 60 reqTimeOut 300 respTimeOut 300 }

Create custom security rules

Add application-specific security rules that complement the OWASP Core Rule Set with custom threat detection.

# Custom ModSecurity Rules for Enhanced Protection

Block common attack patterns

SecRule REQUEST_URI "@detectSQLi" \ "id:100001,\ phase:2,\ block,\ t:urlDecodeUni,\ t:htmlEntityDecode,\ t:normalisePathWin,\ msg:'SQL Injection Attack Detected',\ logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'attack-sqli',\ tag:'paranoia-level/1',\ ver:'OWASP_CRS/3.3.5',\ severity:'CRITICAL',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'"

Rate limiting for specific endpoints

SecRule REQUEST_URI "@beginsWith /wp-login.php" \ "id:100002,\ phase:2,\ pass,\ setvar:'ip.login_attempts=+1',\ expirevar:'ip.login_attempts=300',\ nolog" SecRule IP:LOGIN_ATTEMPTS "@gt 5" \ "id:100003,\ phase:2,\ deny,\ status:429,\ msg:'Rate limit exceeded for login attempts',\ logdata:'IP: %{REMOTE_ADDR} exceeded login rate limit',\ setvar:'ip.login_block=1',\ expirevar:'ip.login_block=1800'"

Block known malicious user agents

SecRule REQUEST_HEADERS:User-Agent "@pmFromFile /usr/local/modsecurity/malicious-ua.txt" \ "id:100004,\ phase:1,\ block,\ msg:'Malicious User Agent Detected',\ logdata:'User-Agent: %{MATCHED_VAR}',\ tag:'attack-reputation-scanner',\ severity:'WARNING'"

Geo-blocking (example for specific countries)

SecRule REMOTE_ADDR "@geoLookup" \ "id:100005,\ phase:1,\ pass,\ nolog,\ setvar:'tx.country_code=%{geo.country_code}'" SecRule TX:COUNTRY_CODE "@in CN RU" \ "id:100006,\ phase:1,\ deny,\ status:403,\ msg:'Access denied from restricted country',\ logdata:'Country: %{tx.country_code}, IP: %{REMOTE_ADDR}'"

File upload restrictions

SecRule FILES_TMPNAMES "@inspectFile /usr/local/modsecurity/util/av.sh" \ "id:100007,\ phase:2,\ block,\ msg:'Malicious file upload detected',\ logdata:'File: %{MATCHED_VAR}'"

Slow HTTP attack protection

SecRule &REQUEST_HEADERS:Content-Length "@eq 0" \ "id:100008,\ phase:1,\ pass,\ nolog,\ setvar:'ip.slow_dos_counter=+1',\ expirevar:'ip.slow_dos_counter=60'" SecRule IP:SLOW_DOS_COUNTER "@gt 30" \ "id:100009,\ phase:1,\ deny,\ status:429,\ msg:'Slow DoS attack detected',\ setvar:'ip.slow_dos_block=1',\ expirevar:'ip.slow_dos_block=600'"

Create malicious user agent blocklist

Maintain a list of known malicious user agents and scanning tools to block automated attacks.

Nikto
Sqlmap
WPScan
DirBuster
ZmEu
LWP::Simple
BBBike
wget
curl/7.0
libwww-perl
python-requests
Masscan
Zmap
Nmap Scripting Engine
OpenVAS
w3af
acunetix
havij
fimap
commix
injectx
vega
burpsuite
owasp zap
Apache-HttpClient

Configure security event monitoring

Set up comprehensive logging and create monitoring scripts to track security events and potential threats.

sudo mkdir -p /var/log/openlitespeed
sudo touch /var/log/openlitespeed/modsec_audit.log
sudo touch /var/log/openlitespeed/modsec_debug.log
sudo touch /var/log/openlitespeed/security_events.log
sudo chown lsadm:lsadm /var/log/openlitespeed/modsec_*.log
sudo chmod 644 /var/log/openlitespeed/modsec_*.log

Create security monitoring script

Build an automated monitoring system that parses security logs and sends alerts when threats are detected.

#!/bin/bash

ModSecurity Log Monitor Script

LOG_FILE="/var/log/openlitespeed/modsec_audit.log" ALERT_EMAIL="admin@example.com" TMP_FILE="/tmp/modsec_alerts.tmp" LAST_CHECK="/var/lib/modsecurity/last_check"

Create state directory

sudo mkdir -p /var/lib/modsecurity sudo chown lsadm:lsadm /var/lib/modsecurity

Function to send alert

send_alert() { local subject="$1" local message="$2" echo "$message" | mail -s "$subject" "$ALERT_EMAIL" logger "ModSecurity Alert: $subject" }

Check for new security events

if [ -f "$LAST_CHECK" ]; then LAST_TIME=$(cat "$LAST_CHECK") else LAST_TIME="1 hour ago" fi

Find new critical events

find "$LOG_FILE" -newer "$LAST_CHECK" 2>/dev/null | while read -r line; do if echo "$line" | grep -q "severity.CRITICAL\|severity.ERROR"; then ATTACK_TYPE=$(echo "$line" | grep -oP 'msg:"\K[^"]*') SOURCE_IP=$(echo "$line" | grep -oP 'client: \K[^,]*') TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S') echo "[$TIMESTAMP] Critical security event detected" >> "$TMP_FILE" echo "Attack Type: $ATTACK_TYPE" >> "$TMP_FILE" echo "Source IP: $SOURCE_IP" >> "$TMP_FILE" echo "Details: $line" >> "$TMP_FILE" echo "---" >> "$TMP_FILE" fi done

Send alerts if events found

if [ -s "$TMP_FILE" ]; then send_alert "ModSecurity Critical Events Detected" "$(cat $TMP_FILE)" rm -f "$TMP_FILE" fi

Update last check timestamp

date > "$LAST_CHECK"

Generate daily statistics

if [ "$(date +%H:%M)" = "09:00" ]; then YESTERDAY=$(date -d "yesterday" +%Y-%m-%d) STATS_FILE="/tmp/modsec_daily_stats.tmp" echo "ModSecurity Daily Report - $YESTERDAY" > "$STATS_FILE" echo "=====================================" >> "$STATS_FILE" echo "" >> "$STATS_FILE" # Count attacks by type echo "Top Attack Types:" >> "$STATS_FILE" grep "$YESTERDAY" "$LOG_FILE" | grep -oP 'attack-\K[^,]*' | sort | uniq -c | sort -nr | head -10 >> "$STATS_FILE" echo "" >> "$STATS_FILE" # Top source IPs echo "Top Source IPs:" >> "$STATS_FILE" grep "$YESTERDAY" "$LOG_FILE" | grep -oP 'client: \K[^,]*' | sort | uniq -c | sort -nr | head -10 >> "$STATS_FILE" echo "" >> "$STATS_FILE" # Blocked requests count BLOCKED_COUNT=$(grep -c "$YESTERDAY.*block" "$LOG_FILE") echo "Total Blocked Requests: $BLOCKED_COUNT" >> "$STATS_FILE" send_alert "ModSecurity Daily Statistics" "$(cat $STATS_FILE)" rm -f "$STATS_FILE" fi

Make monitoring script executable and schedule

Set proper permissions and create a cron job to run the security monitoring script regularly.

sudo chmod +x /usr/local/bin/modsec-monitor.sh
sudo chown lsadm:lsadm /usr/local/bin/modsec-monitor.sh

Add to crontab for regular monitoring

(crontab -l 2>/dev/null; echo "/10 * /usr/local/bin/modsec-monitor.sh >/dev/null 2>&1") | crontab -

Configure log rotation

Set up log rotation to prevent security logs from consuming excessive disk space while maintaining historical data.

/var/log/openlitespeed/modsec_*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    create 644 lsadm lsadm
    postrotate
        /usr/local/lsws/bin/lshttpd -k usr1 >/dev/null 2>&1 || true
    endscript
}

Restart OpenLiteSpeed with security configuration

Apply all security configurations by restarting OpenLiteSpeed and enabling the new WAF and rate limiting rules.

sudo systemctl restart lsws
sudo systemctl enable lsws
sudo systemctl status lsws

Verify your setup

Test the ModSecurity WAF installation and rate limiting functionality to ensure proper protection.

# Check OpenLiteSpeed status
sudo systemctl status lsws

Verify ModSecurity is loaded

sudo /usr/local/lsws/bin/lshttpd -t

Test WAF with a simulated SQL injection

curl -X GET "http://example.com/index.php?id=1' OR '1'='1"

Check security logs for blocked request

sudo tail -f /var/log/openlitespeed/modsec_audit.log

Test rate limiting

for i in {1..25}; do curl -s http://example.com/ > /dev/null; done

Verify custom rules are active

grep -c "Custom ModSecurity Rules" /usr/local/modsecurity/custom-rules.conf

Configure alerting integration

Integrate security monitoring with external alerting systems for immediate threat response.

Install and configure mail system

Set up email notifications for security alerts using a lightweight mail transfer agent.

sudo apt install -y postfix mailutils
sudo dpkg-reconfigure postfix
sudo dnf install -y postfix mailx
sudo systemctl enable --now postfix

Create Slack webhook integration

Add Slack notifications for real-time security alerts to your team communication channel.

#!/bin/bash

Slack notification script for ModSecurity alerts

SLACK_WEBHOOK="https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK" CHANNEL="#security-alerts" USERNAME="ModSecurity-Bot" send_slack_alert() { local message="$1" local color="$2" payload=$(cat <Usage: ./slack-notify.sh "Alert message" "danger" send_slack_alert "$1" "${2:-warning}"

Configure fail2ban integration

Integrate ModSecurity with fail2ban for automatic IP blocking based on attack patterns.

[Definition]
failregex = ModSecurity: Access denied with code \d+ \(phase \d+\)\. \[file "."\] \[line "\d+"\] \[id "\d+"\] \[rev "\d+"\] \[msg "."\] \[data "."\] \[severity "."\] \[ver "."\] \[maturity "\d+"\] \[accuracy "\d+"\] \[hostname "."\] \[uri "."\] \[unique_id "."\] \[ref ".*"\] 

ignoreregex =

Create fail2ban jail for ModSecurity

Configure automatic IP banning for repeated security violations detected by ModSecurity.

[modsecurity]
enabled = true
port = http,https
filter = modsecurity
logpath = /var/log/openlitespeed/modsec_audit.log
maxretry = 3
bantime = 3600
findtime = 600
action = iptables-multiport[name=ModSecurity, port="http,https", protocol=tcp]
         sendmail-whois[name=ModSecurity, dest=admin@example.com, sender=fail2ban@example.com]

Performance tuning

Optimize ModSecurity and rate limiting settings for maximum security with minimal performance impact.

Tune ModSecurity performance settings

Adjust ModSecurity configuration to balance security coverage with server performance.

# Performance optimization for ModSecurity

Reduce rule processing overhead

SecRuleEngine On SecRequestBodyAccess On SecResponseBodyAccess Off

Optimize memory usage

SecRequestBodyLimit 10485760 SecRequestBodyNoFilesLimit 131072 SecRequestBodyInMemoryLimit 131072

Tune regex limits

SecPcreMatchLimit 100000 SecPcreMatchLimitRecursion 100000

Disable unnecessary features in production

SecArgumentSeparator & SecCookieFormat 0 SecUnicodeMapFile unicode.mapping 20127

Optimize collection storage

SecCollectionTimeout 600 SecHttpBlKey whdkfieyhtnf

Cache optimization

SecRuleUpdateActionById 901320 "pass,nolog" SecRuleUpdateActionById 901330 "pass,nolog" SecRuleUpdateActionById 901340 "pass,nolog"

Whitelist trusted IPs (adjust as needed)

SecRule REMOTE_ADDR "@ipMatch 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16" \ "id:999001,\ phase:1,\ pass,\ nolog,\ ctl:ruleEngine=off"

Exclude static files from inspection

SecRule REQUEST_FILENAME "@rx \.(jpg|jpeg|png|gif|css|js|ico|pdf|zip)$" \ "id:999002,\ phase:1,\ pass,\ nolog,\ ctl:ruleEngine=off"

Configure caching for better performance

Enable OpenLiteSpeed caching to reduce the load on security processing while maintaining protection.

# Cache Configuration for Security Performance
cache {
  enableCache              1
  cacheStorePath           /tmp/lshttpd/cache
  cacheSizeMax             200M
  enablePublicCache        1
  enablePrivateCache       0
  checkPrivateCache        1
  checkPublicCache         1
  maxCacheObjSize          10M
  maxStaleAge             200
  qsCache                 1
  reqCookieCache          1
  respCookieCache         1
  ignoreReqCacheCtrl      1
  ignoreRespCacheCtrl     0
  expireInSeconds         3600
  enableStale             0
  staleAge               200
}

Cache policy for static resources

cachepolicy { enableCache 1 expireInSeconds 86400 noCacheRequestHeader "Authorization,Cookie" noCacheResponseHeader "Set-Cookie,Vary,*" enablePublicCache 1 maxStaleAge 3600 }

Common issues

SymptomCauseFix
ModSecurity not blocking attacksRules not loaded properlyCheck /var/log/openlitespeed/modsec_debug.log and verify include paths
False positive blocks legitimate trafficOverly aggressive rule configurationReview and whitelist specific IPs or patterns in custom rules
High server load with WAF enabledInefficient rule processingTune SecPcreMatchLimit and disable response body inspection
Rate limiting not workingConfiguration syntax errorCheck OpenLiteSpeed error log and validate configuration with lshttpd -t
Security logs not rotatingIncorrect logrotate configurationVerify file permissions and test with logrotate -d /etc/logrotate.d/modsecurity
Email alerts not sendingMail system not configuredTest mail system with echo "test" | mail -s "test" admin@example.com
Important: Always test WAF rules in a staging environment before deploying to production. False positives can block legitimate users and impact business operations.

Next steps

Running this in production?

Want this handled for you? Setting up comprehensive WAF protection is complex, but maintaining rule updates, monitoring false positives, and responding to security events 24/7 is the bigger challenge. See how we run infrastructure like this for European SaaS and e-commerce teams.

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle infrastructure security hardening for businesses that depend on uptime. From initial setup to ongoing operations.