waf: Hochleistungs-WAF, gebaut auf dem nginx-module-lua-Stack
Installation
Wenn Sie das RPM-Repository-Abonnement noch nicht eingerichtet haben, melden Sie sich an. Dann können Sie mit den folgenden Schritten fortfahren.
CentOS/RHEL 7 oder Amazon Linux 2
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install lua-resty-waf
CentOS/RHEL 8+, Fedora Linux, Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-waf
Um diese Lua-Bibliothek mit NGINX zu verwenden, stellen Sie sicher, dass nginx-module-lua installiert ist.
Dieses Dokument beschreibt lua-resty-waf v0.11.1, das am 09. Mai 2017 veröffentlicht wurde.
lua-resty-waf ist ein Reverse-Proxy-WAF, der mit dem OpenResty-Stack erstellt wurde. Es nutzt die Nginx Lua API, um HTTP-Anforderungsinformationen zu analysieren und gegen eine flexible Regelstruktur zu verarbeiten. lua-resty-waf wird mit einem Regelset verteilt, das das ModSecurity CRS nachahmt, sowie einigen benutzerdefinierten Regeln, die während der ursprünglichen Entwicklung und Tests erstellt wurden, und einem kleinen virtuellen Patchset für aufkommende Bedrohungen. Darüber hinaus wird lua-resty-waf mit Werkzeugen verteilt, um vorhandene ModSecurity-Regeln automatisch zu übersetzen, sodass Benutzer die Implementierung von lua-resty-waf erweitern können, ohne eine neue Regel-Syntax lernen zu müssen.
lua-resty-waf wurde ursprünglich von Robert Paprocki für seine Masterarbeit an der Western Governor's University entwickelt.
./configure --with-pcre=/path/to/pcre/source --with-pcre-jit
Sie können den PCRE-Quellcode von der [PCRE-Website](http://www.pcre.org/) herunterladen. Siehe auch diesen [Blogbeitrag](https://www.cryptobells.com/building-openresty-with-pcre-jit/) für eine Schritt-für-Schritt-Anleitung zum Erstellen von OpenResty mit einer JIT-aktivierten PCRE-Bibliothek.
## Leistung
lua-resty-waf wurde mit Effizienz und Skalierbarkeit im Hinterkopf entwickelt. Es nutzt das asynchrone Verarbeitungsmodell von Nginx und ein effizientes Design, um jede Transaktion so schnell wie möglich zu verarbeiten. Lasttests haben gezeigt, dass Deployments, die alle bereitgestellten Regelsets implementieren, die darauf ausgelegt sind, die Logik hinter dem ModSecurity CRS nachzuahmen, Transaktionen in etwa 300-500 Mikrosekunden pro Anfrage verarbeiten; dies entspricht der Leistung, die von [Cloudflare's WAF](https://www.cloudflare.com/waf) beworben wird. Die Tests wurden auf einem angemessenen Hardware-Stack (E3-1230 CPU, 32 GB RAM, 2 x 840 EVO im RAID 0) durchgeführt, mit maximal etwa 15.000 Anfragen pro Sekunde. Weitere Informationen finden Sie in [diesem Blogbeitrag](http://www.cryptobells.com/freewaf-a-high-performance-scalable-open-web-firewall).
Die Arbeitslast von lua-resty-waf ist fast ausschließlich CPU-gebunden. Der Speicherbedarf in der Lua-VM (ohne persistenten Speicher, der durch `lua-shared-dict` unterstützt wird) beträgt etwa 2 MB.
## make && sudo make install
Alternativ können Sie über Luarocks installieren:
### process_multipart_body
*Standard* true
Aktivieren Sie die Verarbeitung von multipart/form-data-Anforderungsinhalten (wenn vorhanden) mit dem `lua-resty-upload`-Modul. In Zukunft kann lua-resty-waf diese Verarbeitung nutzen, um strengere Überprüfungen von Upload-Inhalten durchzuführen; derzeit führt dieses Modul nur minimale Plausibilitätsprüfungen des Anforderungsinhalts durch und protokolliert kein Ereignis, wenn der Anforderungsinhalt ungültig ist. Deaktivieren Sie diese Option, wenn Sie diese Überprüfung nicht benötigen oder wenn Fehler im upstream-Modul Probleme mit HTTP-Uploads verursachen.
*Beispiel*:
```lua
location / {
access_by_lua_block {
-- Deaktivieren Sie die Verarbeitung von multipart/form-data-Anfragen
-- beachten Sie, dass der Anforderungsinhalt weiterhin an den Upstream gesendet wird
waf:set_option("process_multipart_body", false)
}
}
req_tid_header
Standard: false
Setzen Sie einen HTTP-Header X-Lua-Resty-WAF-ID in der Upstream-Anfrage, mit dem Wert als Transaktions-ID. Diese ID korreliert mit der Transaktions-ID, die in den Debug-Protokollen vorhanden ist (falls gesetzt). Dies kann nützlich sein für die Anforderungsverfolgung oder Debugging-Zwecke.
Beispiel:
location / {
access_by_lua_block {
waf:set_option("req_tid_header", true)
}
}
res_body_max_size
Standard: 1048576 (1 MB)
Definiert die Inhaltslängen-Schwelle, ab der Antwortinhalte nicht mehr verarbeitet werden. Diese Größe des Antwortinhalts wird durch den Content-Length-Antwortheader bestimmt. Wenn dieser Header in der Antwort nicht vorhanden ist, wird der Antwortinhalt niemals verarbeitet.
Beispiel:
location / {
access_by_lua_block {
-- Erhöhen Sie die maximale Antwortgröße auf 2 MB
waf:set_option("res_body_max_size", 1024 * 1024 * 2)
}
}
res_body_mime_types
Standard: "text/plain", "text/html"
Definiert die MIME-Typen, mit denen lua-resty-waf den Antwortinhalt verarbeitet. Dieser Wert wird durch den Content-Type-Header bestimmt. Wenn dieser Header nicht vorhanden ist oder der Antworttyp nicht in dieser Liste enthalten ist, wird der Antwortinhalt nicht verarbeitet. Das Setzen dieser Option fügt den angegebenen MIME-Typ zu den bestehenden Standardwerten von text/plain und text/html hinzu.
Beispiel:
location / {
access_by_lua_block {
-- Die MIME-Typen, die verarbeitet werden, sind jetzt text/plain, text/html und text/json
waf:set_option("res_body_mime_types", "text/json")
}
}
Mehrere MIME-Typen können hinzugefügt werden, indem eine Tabelle von Typen an set_option übergeben wird.
res_tid_header
Standard: false
Setzen Sie einen HTTP-Header X-Lua-Resty-WAF-ID in der Downstream-Antwort, mit dem Wert als Transaktions-ID. Diese ID korreliert mit der Transaktions-ID, die in den Debug-Protokollen vorhanden ist (falls gesetzt). Dies kann nützlich sein für die Anforderungsverfolgung oder Debugging-Zwecke.
Beispiel:
location / {
access_by_lua_block {
waf:set_option("res_tid_header", true)
}
}
score_threshold
Standard: 5
Setzt die Schwelle für die Anomalie-Bewertung. Wenn die Schwelle erreicht ist, wird lua-resty-waf die Anfrage ablehnen.
Beispiel:
location / {
access_by_lua_block {
waf:set_option("score_threshold", 10)
}
}
storage_backend
Standard: dict
Definieren Sie eine Engine, die für die persistenten Variablen gespeichert wird. Derzeit verfügbare Optionen sind dict (ngx_lua Shared Memory-Zone), memcached und redis.
Beispiel:
location / {
access_by_lua_block {
waf:set_option("storage_backend", "memcached")
}
}
storage_keepalive
Standard: true
Aktivieren oder deaktivieren Sie TCP Keepalive für Verbindungen zu Remote-Persistent-Speicher-Hosts.
Beispiel:
location / {
access_by_lua_block {
waf:set_option("storage_keepalive", false)
}
}
storage_keepalive_timeout
Standard: 10000
Konfigurieren Sie (in Millisekunden) den Timeout für den Cosocket-Keepalive-Pool für Remote-Persistent-Speicher-Hosts.
Beispiel:
location / {
access_by_lua_block {
waf:set_option("storage_keepalive_timeout", 30000)
}
}
storage_keepalive_pool_size
Standard: 100
Konfigurieren Sie die Poolgröße für den Cosocket-Keepalive-Pool für Remote-Persistent-Speicher-Hosts.
Beispiel:
location / {
access_by_lua_block {
waf:set_option("storage_keepalive_pool_size", 50)
}
}
storage_memcached_host
Standard: 127.0.0.1
Definieren Sie einen Host, der verwendet werden soll, wenn memcached als Engine für die Speicherung persistenter Variablen verwendet wird.
Beispiel:
location / {
access_by_lua_block {
waf:set_option("storage_memcached_host", "10.10.10.10")
}
}
storage_memcached_port
Standard: 11211
Definieren Sie einen Port, der verwendet werden soll, wenn memcached als Engine für die Speicherung persistenter Variablen verwendet wird.
Beispiel:
location / {
access_by_lua_block {
waf:set_option("storage_memcached_port", 11221)
}
}
storage_redis_host
Standard: 127.0.0.1
Definieren Sie einen Host, der verwendet werden soll, wenn redis als Engine für die Speicherung persistenter Variablen verwendet wird.
Beispiel:
location / {
access_by_lua_block {
waf:set_option("storage_redis_host", "10.10.10.10")
}
}
storage_redis_port
Standard: 6379
Definieren Sie einen Port, der verwendet werden soll, wenn redis als Engine für die Speicherung persistenter Variablen verwendet wird.
Beispiel:
location / {
access_by_lua_block {
waf:set_option("storage_redis_port", 6397)
}
}
storage_zone
Standard: none
Definiert das lua_shared_dict, das verwendet wird, um Daten für die persistente Speicherung zu halten. Diese Zone muss im http{}-Block der Konfiguration definiert werden.
Beispiel:
http {
-- Definieren Sie eine 64M Shared Memory-Zone, um Daten für die persistente Speicherung zu halten
lua_shared_dict persistent_storage 64m;
}
location / {
access_by_lua_block {
waf:set_option("storage_zone", "persistent_storage")
}
}
Mehrere Shared Zones können definiert und verwendet werden, obwohl nur eine Zone pro Konfigurationsort definiert werden kann. Wenn eine Zone voll wird und die Schnittstelle des Shared Dictionary keine zusätzlichen Schlüssel hinzufügen kann, wird Folgendes in das Fehlerprotokoll eingegeben:
Fehler beim Hinzufügen des Schlüssels zur persistenten Speicherung, erhöhen Sie die Größe des lua_shared_dict
Phasenverarbeitung
lua-resty-waf ist so konzipiert, dass es in mehreren Phasen des Anforderungslebenszyklus ausgeführt wird. Regeln können in den folgenden Phasen verarbeitet werden:
- access: Anforderungsinformationen wie URI, Anforderungsheader, URI-Argumente und Anforderungsinhalt sind in dieser Phase verfügbar.
- header_filter: Antwortheader und HTTP-Status sind in dieser Phase verfügbar.
- body_filter: Der Antwortinhalt ist in dieser Phase verfügbar.
- log: Ereignisprotokolle werden automatisch am Ende dieser Phase geschrieben.
Diese Phasen entsprechen ihren entsprechenden Nginx-Lua-Handlern (access_by_lua, header_filter_by_lua, body_filter_by_lua und log_by_lua). Beachten Sie, dass das Ausführen von lua-resty-waf in einem Lua-Phasenhandler, der nicht in dieser Liste enthalten ist, zu fehlerhaftem Verhalten führen wird. Alle Daten, die in einer früheren Phase verfügbar sind, sind auch in einer späteren Phase verfügbar. Das heißt, Daten, die in der access-Phase verfügbar sind, sind auch in den Phasen header_filter und body_filter verfügbar, aber nicht umgekehrt.
Eingeschlossene Regelsets
lua-resty-waf wird mit einer Reihe von Regelsets verteilt, die darauf ausgelegt sind, die Funktionalität des ModSecurity CRS nachzuahmen. Zur Referenz sind diese Regelsets hier aufgelistet:
- 11000_whitelist: Lokale Richtlinien-Whitelist
- 20000_http_violation: HTTP-Protokollverletzung
- 21000_http_anomaly: HTTP-Protokollanomalien
- 35000_user_agent: Bösartige/verdächtige Benutzeragenten
- 40000_generic_attack: Generische Angriffe
- 41000_sqli: SQLi
- 42000_xss: XSS
- 90000_custom: Benutzerdefinierte Regeln/virtuelles Patchen
- 99000_scoring: Anomalie-Bewertungshandhabung
Regeldefinitionen
lua-resty-waf analysiert Regeldefinitionen aus JSON-Blobs, die auf der Festplatte gespeichert sind. Regeln werden basierend auf Zweck und Schwere in einem Regelset gruppiert. Die enthaltenen Regelsets wurden erstellt, um einige Funktionen des ModSecurity CRS nachzuahmen, insbesondere die base_rules-Definitionen. Darüber hinaus kann das enthaltene Skript modsec2lua-resty-waf.pl verwendet werden, um zusätzliche oder benutzerdefinierte Regelsets in ein lua-resty-waf-kompatibles JSON-Blob zu übersetzen.
Beachten Sie, dass es mehrere Einschränkungen im Übersetzungsskript gibt, die sich auf nicht unterstützte Aktionen, Sammlungen und Operatoren beziehen. Bitte sehen Sie sich diese Wiki-Seite für eine aktuelle Liste bekannter Inkompatibilitäten an.
Hinweise
Pull-Requests
Bitte richten Sie alle Pull-Requests an den Entwicklungszweig oder einen Feature-Zweig, wenn der PR eine wesentliche Änderung darstellt. Commits in den Master sollten nur in Form von Dokumentationsaktualisierungen oder anderen Änderungen erfolgen, die keinen Einfluss auf das Modul selbst haben (und sauber in die Entwicklung integriert werden können).
Roadmap
- Erweitertes virtuelles Patch-Regelset: Erhöhen Sie die Abdeckung aufkommender Bedrohungen.
- Erweiterte Integrations-/Akzeptanztests: Erhöhen Sie die Abdeckung häufiger Bedrohungen und Nutzungsszenarien.
- Erweiterte ModSecurity-Syntaxübersetzungen: Unterstützung für mehr Operatoren, Variablen und Aktionen.
- Gemeinsame Anwendungsprofile: Abgestimmte Regelsets für gängige CMS/Anwendungen.
- Unterstützung mehrerer Socket-/Datei-Logger-Ziele: Wahrscheinlich erforderlich, um das Projekt lua-resty-logger-socket zu forken.
Einschränkungen
lua-resty-waf befindet sich in kontinuierlicher Entwicklung und Verbesserung und kann daher in seiner Funktionalität und Leistung eingeschränkt sein. Derzeit bekannte Einschränkungen finden Sie im GitHub-Issue-Tracker für dieses Repo.
Siehe auch
- Das OpenResty-Projekt: http://openresty.org/
- Mein persönlicher Blog für Updates und Notizen zur Entwicklung von lua-resty-waf: http://www.cryptobells.com/tag/lua-resty-waf/
GitHub
Sie finden möglicherweise zusätzliche Konfigurationstipps und Dokumentationen für dieses Modul im GitHub-Repository für nginx-module-waf.