SiamCafe · Blog
ModSecurity WAF Production Setup Guide — ตั้งค่า
บทความ

ModSecurity WAF Production Setup Guide — ตั้งค่า

เผยแพร่ 28 พฤษภาคม 2569

ModSecurity WAF

ModSecurity WAF Production Setup Guide — ตั้งค่า

ModSecurity WAF Production Setup OWASP CRS Nginx Apache SQL Injection XSS Rule Anomaly Scoring Paranoia Level Audit Log

FeatureModSecurity v2ModSecurity v3Cloud WAF (AWS/CF)
ArchitectureEmbedded Modulelibmodsecurity + ConnectorManaged Service
Web ServerApache onlyNginx, Apache, IISAny (Proxy)
OWASP CRSรองรับรองรับManaged Rules
Costฟรี (OSS)ฟรี (OSS)$5-100+/เดือน
Maintenanceสูง (Self-managed)สูง (Self-managed)ต่ำ (Managed)
Customizationสูงมากสูงมากปานกลาง

Installation & Configuration

# === ModSecurity v3 + Nginx + OWASP CRS ===

# Docker (Easiest)
# docker run -d --name modsec-nginx \
#   -p 80:80 -p 443:443 \
#   -v /etc/nginx/conf.d:/etc/nginx/conf.d \
#   -v /etc/modsecurity:/etc/modsecurity \
#   owasp/modsecurity-crs:nginx-alpine

# Manual Install (Ubuntu/Debian)
# apt install -y libmodsecurity3 libmodsecurity-dev
# git clone https://github.com/SpiderLabs/ModSecurity-nginx
# # Compile Nginx with ModSecurity connector
# nginx -V 2>&1 | grep -o 'configure arguments:.*'
# ./configure --add-dynamic-module=../ModSecurity-nginx [original args]
# make modules
# cp objs/ngx_http_modsecurity_module.so /etc/nginx/modules/

# nginx.conf
# load_module modules/ngx_http_modsecurity_module.so;
# http {
#     modsecurity on;
#     modsecurity_rules_file /etc/modsecurity/modsecurity.conf;
# }

# modsecurity.conf
# SecRuleEngine DetectionOnly  # Start with DetectionOnly, change to On later
# SecRequestBodyAccess On
# SecResponseBodyAccess Off
# SecAuditEngine RelevantOnly
# SecAuditLog /var/log/modsecurity/audit.log
# SecAuditLogFormat JSON
# SecTmpDir /tmp/modsecurity
# SecDataDir /tmp/modsecurity

# OWASP CRS Setup
# git clone https://github.com/coreruleset/coreruleset /etc/modsecurity/crs
# cp /etc/modsecurity/crs/crs-setup.conf.example /etc/modsecurity/crs/crs-setup.conf
# # Edit crs-setup.conf: Set Paranoia Level
# SecAction "id:900000, phase:1, pass, t:none, nolog, setvar:tx.paranoia_level=1"
# SecAction "id:900110, phase:1, pass, t:none, nolog, setvar:tx.inbound_anomaly_score_threshold=5"

from dataclasses import dataclass

@dataclass
class InstallOption:
    method: str
    difficulty: str
    time: str
    pros: str
    cons: str

options = [
    InstallOption("Docker (owasp/modsecurity-crs)",
        "ง่าย",
        "10 นาที",
        "พร้อมใช้ CRS ในตัว Update ง่าย Reproducible",
        "ต้องรู้ Docker Customize ยากกว่า"),
    InstallOption("Package Manager (apt/yum)",
        "ปานกลาง",
        "30 นาที",
        "ติดตั้งง่าย ใช้ Package ของ Distro",
        "เวอร์ชันอาจเก่า Limited Config"),
    InstallOption("Compile from Source",
        "ยาก",
        "1-2 ชั่วโมง",
        "เวอร์ชันล่าสุด Full Control Optimize",
        "ต้อง Compile เอง Maintain เอง"),
]

print("=== Install Options ===")
for o in options:
    print(f"  [{o.method}] Difficulty: {o.difficulty} | Time: {o.time}")
    print(f"    Pros: {o.pros}")
    print(f"    Cons: {o.cons}")

Rule Tuning

ModSecurity WAF Production Setup Guide — ตั้งค่า
# === ModSecurity Rule Tuning ===

# Rule Exclusion Examples
# # Remove specific rule for specific URL
# SecRule REQUEST_URI "@beginsWith /api/upload" \
#   "id:1001, phase:1, pass, nolog, ctl:ruleRemoveById=942100"
#
# # Remove rule for specific parameter
# SecRule REQUEST_URI "@beginsWith /admin" \
#   "id:1002, phase:1, pass, nolog, ctl:ruleRemoveTargetById=942100;ARGS:content"
#
# # Whitelist IP address
# SecRule REMOTE_ADDR "@ipMatch 10.0.0.0/8,192.168.0.0/16" \
#   "id:1003, phase:1, pass, nolog, ctl:ruleEngine=Off"
#
# # Increase anomaly threshold for API endpoints
# SecRule REQUEST_URI "@beginsWith /api/" \
#   "id:1004, phase:1, pass, nolog, setvar:tx.inbound_anomaly_score_threshold=10"

@dataclass
class TuningRule:
    issue: str
    rule_id: str
    description: str
    fix: str
    example: str

tuning_rules = [
    TuningRule("File Upload blocked",
        "942100 (SQLi)",
        "Upload content triggers SQL Injection rule",
        "Exclude rule for upload path",
        "ctl:ruleRemoveById=942100 for /api/upload"),
    TuningRule("Rich Text Editor blocked",
        "941xxx (XSS)",
        "HTML content in editor triggers XSS rules",
        "Exclude XSS rules for editor parameter",
        "ctl:ruleRemoveTargetById=941100;ARGS:content"),
    TuningRule("API JSON body blocked",
        "920xxx (Protocol)",
        "JSON body triggers content-type rules",
        "Set correct content-type handling",
        "SecRule REQUEST_HEADERS:Content-Type '@contains json'"),
    TuningRule("Scanner false positive",
        "913xxx (Scanner)",
        "Monitoring tool triggers scanner detection",
        "Whitelist monitoring IP/User-Agent",
        "SecRule REMOTE_ADDR '@ipMatch 10.0.0.0/8' pass"),
    TuningRule("Large request body",
        "920xxx (Limit)",
        "Large POST body exceeds limit",
        "Increase body limit for specific paths",
        "SecRequestBodyLimit 13107200 (for upload)"),
]

print("=== Tuning Rules ===")
for t in tuning_rules:
    print(f"\n  [{t.issue}] Rule: {t.rule_id}")
    print(f"    Desc: {t.description}")
    print(f"    Fix: {t.fix}")
    print(f"    Example: {t.example}")

Monitoring & Logging

# === ModSecurity Monitoring ===

@dataclass
class LogMetric:
    metric: str
    source: str
    alert: str
    dashboard: str

monitoring = [
    LogMetric("Blocked Requests/min",
        "Audit Log (JSON) → ELK/Loki",
        "> 100/min → Possible Attack or False Positive",
        "Time Series Graph blocked requests over time"),
    LogMetric("Top Blocked Rules",
        "Audit Log rule_id field",
        "Single rule > 50% of blocks → Needs Tuning",
        "Bar Chart top 10 triggered rules"),
    LogMetric("Top Blocked IPs",
        "Audit Log client_ip field",
        "Single IP > 100 blocks/hr → Add to Blocklist",
        "Table top 10 blocked source IPs"),
    LogMetric("Anomaly Score Distribution",
        "Audit Log anomaly_score",
        "Many scores near threshold → Adjust threshold",
        "Histogram anomaly score distribution"),
    LogMetric("False Positive Rate",
        "Manual review blocked legitimate requests",
        "> 1% of legitimate traffic blocked → Tune rules",
        "Stat panel FP rate percentage"),
    LogMetric("Attack Categories",
        "Audit Log rule tags (SQLi, XSS, RCE)",
        "New attack type spike → Investigate",
        "Pie chart attack type distribution"),
]

print("=== Monitoring Metrics ===")
for m in monitoring:
    print(f"  [{m.metric}]")
    print(f"    Source: {m.source}")
    print(f"    Alert: {m.alert}")
    print(f"    Dashboard: {m.dashboard}")

เคล็ดลับ

  • DetectionOnly: เริ่ม DetectionOnly ดู Log 1-2 สัปดาห์ก่อน Block
  • Paranoia 1: เริ่ม Paranoia Level 1 ค่อยๆ เพิ่ม
  • JSON Log: ใช้ JSON Audit Log ง่ายต่อ Parse ด้วย ELK/Loki
  • Whitelist: Whitelist Monitoring IP Internal Services
  • Test: ทดสอบ Regression หลังทุกการ Tune Rule

ModSecurity คืออะไร

Open Source WAF SQL Injection XSS CSRF RCE Apache Nginx Module OWASP CRS Rule-based Audit Log Anomaly Scoring ฟรี