WAF-Regeln
WAF-Regeln sind der programmierbare Teil der Sicherheitsschicht von smoxy. Während die verwaltete WAF und die verwalteten Szenarien die Entscheidung abnehmen, beschreibt eine WAF-Regel die eigene Vorgabe: welcher Teil einer Anfrage geprüft wird, wie verglichen wird und was am Edge passieren soll, wenn die Regel greift — blockieren, per Challenge prüfen, drosseln, überspringen oder nur den Anomalie-Score der Anfrage erhöhen.
Regeln werden bei jeder Anfrage am Edge ausgewertet, im selben Durchlauf wie die Plattformregeln von smoxy. Eine gespeicherte Änderung ist innerhalb von Momenten aktiv.


INFO
Beta: Die Regel-Engine befindet sich in der Beta-Phase. Von der Plattform verwaltete Regeln gelten für jede Zone, und Details des Regelverhaltens können sich noch ändern.
Wo WAF-Regeln greifen
Die Regel-Engine ist die letzte Stufe der Sicherheitsschicht. Alles, was eine Anfrage ausnehmen kann, ist bereits gelaufen, wenn eine Regel ausgewertet wird:
- 1IP-ListenAllowlist und Blocklist der Zone und global
- 2Access RulesAllow · Block · Challenge · Skip
- 3Reputation & Under Attack ModeVerdikte der verwalteten Szenarien
- 4WAF-Regelneigene und von Smoxy verwaltete Regeln in einer sortierten Liste
Aus dieser Reihenfolge folgen zwei Dinge für die Praxis:
- Eine IP auf der Allowlist, ein verifizierter Suchmaschinen-Crawler oder eine Access Rule mit Allow oder Skip (waf) nimmt die Anfrage aus, bevor die Engine läuft. Keine WAF-Regel bekommt sie zu sehen. Für Monitoring-Werkzeuge und vertrauenswürdige Integrationen ist das der vorgesehene Weg.
- Basic Auth läuft danach und wird von keiner WAF-Regel übersprungen. Eine
skip-Regel verteilt keine Passwörter.
Den vollständigen Ablauf zeigt der Lebenszyklus einer Anfrage.
Zwei Arten von Regeln
Die Karte WAF-Regeln auf der WAF-Seite der Zone enthält zwei Listen:
| Liste | Wem sie gehört | Was möglich ist |
|---|---|---|
| Eigene Regeln | der Zone | anlegen, bearbeiten, löschen, aktivieren/deaktivieren |
| Von Smoxy verwaltete Regeln | smoxy | einzeln für diese Zone ein- oder ausschalten — die Regel selbst ist schreibgeschützt |
Beide Listen werden am Edge zu einer einzigen Auswertungsliste zusammengeführt und nach Reihenfolge sortiert. Eine eigene Regel mit Reihenfolge 0 wird also vor einer verwalteten Regel mit Reihenfolge 10 ausgewertet. Verwaltete Regeln behandelt der Abschnitt Von Smoxy verwaltete Regeln.
Regelkontingent
Eine Zone hat standardmäßig 3 eigene WAF-Regeln. Die Karte zeigt eine WAF-Regelnutzung an (2 / 3, „1 Regel übrig“, „Limit erreicht“). Braucht eine Zone mehr, hilft der Support weiter.
Das Kontingent gilt nur für eigene Regeln. Verwaltete Regeln sind unbegrenzt und zählen nicht mit; vom gemeinsamen Kontingent der Access, Rewrite und Conditional Rules ist es ebenfalls getrennt.
Eine Regel anlegen
- Die Seite WAF der Zone öffnen (Sicherheit → WAF).
- In der Karte WAF-Regeln auf Regel hinzufügen klicken.
- Beschreibung, Bedingungen und Aktion ausfüllen.
- Mit Regel hinzufügen speichern.


Felder einer Regel
| Feld | Bedeutung |
|---|---|
| Beschreibung | Ein Etikett mit bis zu 255 Zeichen. Es steht in der Regelliste und in Support-Gesprächen. Wird nie ausgewertet. |
| Aktiviert | Ausgeschaltet bleibt die Regel erhalten, wird aber gar nicht ausgewertet — sie trifft auf nichts zu und liefert keinen Score. |
| Phase | Anfrage — die Regel wird ausgewertet, bevor die Anfrage an den Origin weitergereicht wird. |
| Übereinstimmung | Alle Bedingungen (UND) oder Beliebige Bedingung (ODER). Standard: alle. |
| Reihenfolge | Aufsteigend, kleinere Zahl zuerst. Jede Regel sollte eine eigene Zahl bekommen — bei gleicher Reihenfolge ist die Abfolge offen. |
| Bedingungen | Eine oder mehrere Bedingungszeilen: Ziele, Operator, Muster, optional Transformationen, optional Negieren. |
| Aktion | Was bei einem Treffer geschieht, samt den Parametern, die diese Aktion braucht. |
Reihenfolge ist eine Zahl, die selbst vergeben wird. Lücken (10, 20, 30) machen es leicht, später eine Regel dazwischenzuschieben.
Bedingungen
Eine Bedingung stellt genau eine Frage an die Anfrage: diese Teile der Anfrage nehmen, optional bereinigen und mit diesem Operator gegen dieses Muster prüfen.
Ziele — was geprüft wird
Ein Ziel liefert eine Liste von Werten. Mehrwertige Ziele fächern auf, und der Operator läuft gegen jeden Wert einzeln — deshalb bringt es einem Angreifer nichts, zusätzliche Query-Parameter zu streuen.
| Ziel | Liefert | Anmerkungen |
|---|---|---|
uri | den Anfragepfad | Bereits prozentdekodiert und normalisiert. Ohne Query-String. |
uri.raw | Pfad und Query, unverändert | Genau so, wie der Client sie geschickt hat, ohne Dekodierung. Das einzige Ziel, das Kodierungstricks übersteht — siehe erstes Beispiel. |
query | den rohen Query-String | Alles nach dem ?, weiterhin URL-kodiert, als ein Wert. |
args | jeden Wert eines Query-Parameters | Dekodiert. Wiederholte Parameter fächern auf. Nur Query-String — Formularfelder stehen hier nicht. |
args.names | jeden Namen eines Query-Parameters | Fängt Parameternamen-Sondierungen und Prototype-Pollution-Versuche ab. |
headers | jeden Header-Wert der Anfrage | Alle. Ein wiederholter Header fächert auf. |
headers.user-agent | den Wert dieses Headers | |
headers.referer | den Wert dieses Headers | |
headers.host | den Wert dieses Headers | |
headers.content-type | den Wert dieses Headers | |
cookies | jeden Cookie-Wert | Cookie-Namen lassen sich nicht prüfen. |
body.raw | den gesamten Anfragekörper | Ein Wert, beliebiger Content-Type — auch multipart, das sonst nicht zerlegt wird. |
body.form | jeden Formularfeld-Wert | Nur bei Content-Type x-www-form-urlencoded. |
body.json | jeden Blattwert des JSON | Rekursiv, maximale Tiefe 32. Nur wenn der Content-Type json enthält. Schlüssel werden nicht erfasst, nur Blätter. |
ip | die Client-IP | Die echte Besucheradresse, nicht ein Proxy-Zwischenschritt. Siehe Client-IP. |
method | die HTTP-Methode | Großgeschrieben, z. B. POST. |
host | den Host der Anfrage | |
geoip.country | den ISO-Ländercode | Leer, wenn nicht auflösbar. |
geoip.asn | die AS-Nummer | Numerisch. 0, wenn unbekannt. Mit einem numerischen Operator oder within kombinieren. |
Eine Bedingung darf mehrere Ziele aufführen. Sie ist wahr, sobald irgendein Wert irgendeines aufgeführten Ziels den Operator besteht.
INFO
Anfragekörper werden nur unter Bedingungen geprüft. Ein body.*-Ziel sieht nur dann Daten, wenn die Methode POST, PUT, PATCH oder DELETE lautet, die Content-Length höchstens 256 KB beträgt und der Körper im Arbeitsspeicher geblieben ist. Ein großer Upload wird stillschweigend übergangen — eine Body-Regel deckt also keine Datei-Uploads ab.
Transformationen — die Schicht gegen Verschleierung
Transformationen laufen auf jedem ausgelesenen Wert, von links nach rechts in der angegebenen Reihenfolge, bevor der Operator ihn zu sehen bekommt. Angreifer weichen viel häufiger über Kodierung aus als über neue Nutzlasten. Hier entsteht deshalb der größte Teil der Robustheit.
| Transformation | Was sie macht | Beispiel |
|---|---|---|
lowercase | Setzt den Wert in Kleinbuchstaben. Für ASCII verlässlich. | UNION → union |
uppercase | Setzt den Wert in Großbuchstaben. | abc → ABC |
urlDecode | Dekodiert %XX und macht aus + ein Leerzeichen. | %2e%2e%2f → ../ |
urlDecodeUni | Löst zuerst %uXXXX im IIS-Stil auf, danach die Prozentkodierung. Codepoints ab 256 entfallen. | %u003cscript → <script |
htmlEntityDecode | Löst &#NN;, &#xHH; sowie die benannten Entitäten lt gt amp quot apos nbsp auf. Unbekannte Namen bleiben stehen. | <script> → <script> |
base64Decode | Dekodiert Base64. Schlägt das fehl, geht der ursprüngliche Wert unverändert weiter — der Einsatz auf Verdacht ist also gefahrlos. | c2VsZWN0 → select |
normalizePath | Fasst mehrfache Schrägstriche zusammen und löst . und .. auf. Dekodiert nicht vorher — urlDecode davorsetzen. | /a/./b/../c → /a/c |
removeNulls | Entfernt \0-Bytes, den klassischen Trick zum Zerteilen von Filtern. | ad\0min → admin |
removeWhitespace | Entfernt jedes Leerraumzeichen. | UNION SELECT → UNIONSELECT |
compressWhitespace | Fasst jede Folge von Leerraum zu einem einzelnen Leerzeichen zusammen und erhält damit die Wortgrenzen. | UNION SELECT → UNION SELECT |
length | Ersetzt den Wert durch seine Zeichenanzahl. Gehört zu einem numerischen Operator. Bei einem mehrwertigen Ziel ist das die Länge jedes einzelnen Werts, nicht die Anzahl der Werte. | abcd → 4 |
TIP
Ein vernünftiger Standardsatz. Für die Inhaltsprüfung auf args, body.* oder uri: urlDecode → removeNulls → lowercase. Für XSS kommt htmlEntityDecode dazu, für Path-Traversal normalizePath. Die Reihenfolge zählt: erst dekodieren, dann normalisieren, dann kleinschreiben.
Operatoren — wie verglichen wird
| Operator (Beschriftung) | Wert | Bedeutung | Format des Musters |
|---|---|---|---|
| Entspricht Regex | rx | PCRE-Ausdruck, Teiltreffer ohne Verankerung. Groß-/Kleinschreibung zählt, solange nicht (?i) oder lowercase dazukommt. | (?i)union\s+select |
| SQL-Injection erkennen | detectSQLi | Der SQL-Injection-Detektor von libinjection — dieselbe Bibliothek, die auch die großen Open-Source-WAFs einsetzen. | keins |
| XSS erkennen | detectXSS | Der XSS-Detektor von libinjection. | keins |
| Enthält | contains | Wörtliche Teilzeichenkettensuche, keine Regex-Auswertung. Groß-/Kleinschreibung zählt. | Zeichenkette |
| Gleich (Zeichenkette) | streq | Exakte Gleichheit. Groß-/Kleinschreibung zählt. | Zeichenkette |
| Beginnt mit | beginsWith | Wörtlicher Präfixtest. | Zeichenkette |
| Endet mit | endsWith | Wörtlicher Suffixtest. Ein leeres Muster trifft nie zu. | Zeichenkette |
| Entspricht einer Phrase | pm | Der Wert enthält eines der aufgeführten Literale. Gedacht für lange Stichwortlisten. | durch Leerraum getrennt: sqlmap nikto nmap |
| Ist in Menge enthalten | within | Der Wert ist gleich einem Element der Menge. | durch Leerraum oder Komma getrennt: GET, HEAD |
| IP entspricht | ipMatch | Liest den Wert als IP und prüft ihn gegen eine Menge aus Adressen und CIDRs. IPv4 und IPv6. | 10.0.0.0/8, 2001:db8::/32 |
| ≥ > ≤ < = (numerisch) | ge gt le lt eq | Beide Seiten werden als Zahl gelesen; ein nicht numerischer Wert auf einer Seite ergibt schlicht falsch. Passt zu length oder geoip.asn. | eine Zahl, z. B. 2048 |
WARNING
Die Falle mit der Groß-/Kleinschreibung. Entspricht Regex erzwingt keine Unabhängigkeit von der Schreibweise — das entscheidet die Regel. Fast jeder Fehlschlag einer handgeschriebenen Regel kommt daher, dass union select dort steht und UnIoN SeLeCt daran vorbeigeht. Also (?i)union\s+select schreiben oder die Transformation lowercase ergänzen.
Ein fehlerhaftes Muster bringt nie die Anfrage zu Fall: die Bedingung wird dann einfach falsch.
Bedingungen verknüpfen
Übereinstimmung legt fest, wie die Bedingungszeilen zusammenwirken:
- Alle Bedingungen — jede Zeile muss wahr sein (UND).
- Beliebige Bedingung — mindestens eine Zeile muss wahr sein (ODER).
Verschachtelung gibt es nicht und auch keinen Operator pro Zeile: eine flache Liste, eine Verknüpfung. Für alles Komplexere wird die Logik auf zwei Regeln aufgeteilt.
WARNING
Negieren kehrt die ganze Bedingung um, nicht jeden einzelnen Wert. Bei einem mehrwertigen Ziel bedeutet Negieren kein Wert hat getroffen — nicht irgendein Wert hat nicht getroffen. Eine negierte Bedingung auf args ist falsch, sobald ein einziger Parameter zutrifft.
Genau dieses Verhalten ist zugleich die einzige Möglichkeit, auf Abwesenheit zu prüfen. Ein Ziel ohne Inhalt liefert eine leere Liste, also kann nichts den Operator bestehen und die Bedingung ist falsch; mit eingeschaltetem Negieren wird sie wahr:
Ziele: headers.referer
Operator: Entspricht Regex
Muster: .
Negieren: ein
→ wahr, wenn die Anfrage überhaupt keinen Referer-Header trägtAktionen
| Aktion | Am Edge | Beendet die Anfrage? | Braucht |
|---|---|---|---|
| Blockieren | Liefert die Sicherheitsseite der Zone mit 403 und bricht ab. | ja | Antwort-Status |
| Challenge | Liefert das JavaScript-Proof-of-Work-Interstitial. Wer bereits einen gültigen Nachweis hat, kommt direkt durch. | außer bei gültigem Nachweis | — |
| Drosseln | Bremst die Anfrage, ohne sie abzulehnen. Sie läuft weiter zu Cache und Origin. | nein | Rate und/oder Verzögerung |
| Überspringen | Übernimmt die Entscheidung für diese Anfrage, sodass keine spätere WAF-Regel mehr handeln kann, und vermerkt skip. | nein | — |
| Protokollieren | Hält den Treffer fest und handelt nicht — übernimmt aber ebenfalls die Entscheidung. Siehe die Warnung unten. | nein | — |
| Score | Erhöht den Anomalie-Score der Anfrage und lässt die Auswertung weiterlaufen. Die einzige wirklich passive Aktion. | nein | Score |
Blockieren
Eine blockierte Anfrage wird mit 403 und der Sicherheitsseite der Zone beantwortet, die sich unter Benutzerdefinierte Seiten im eigenen Design gestalten lässt.
Score und die Anomalie-Schwelle
Score entscheidet für sich genommen nichts. Der Wert kommt zu einer laufenden Summe für die Anfrage hinzu, und wenn keine Regel die Entscheidung übernommen hat und die Summe 5 erreicht, wird die Anfrage blockiert. Die Schwelle liegt fest bei 5 und ist pro Zone nicht einstellbar.
Das ist das Mittel für Signale, die verdächtig, aber für sich allein nicht beweiskräftig sind — ein Skript-User-Agent, ein fehlendes Accept-Language, eine ungewöhnliche Methode. Keines davon rechtfertigt eine Blockade; drei davon zusammen unter Umständen schon.
Der Score wird bei jeder Aktion addiert, nicht nur bei Score. Eine blockierende Regel darf also zusätzlich einen Score tragen, damit der Treffer in der Gesamtsumme der Anfrage auftaucht.
Drosseln
Drosseln hat zwei Hebel, und sie treffen unterschiedliche Störenfriede:
- Rate (Bytes/s) begrenzt den Durchsatz des Antwortkörpers. Der Hebel gegen bandbreitenhungrige Scraper.
0heißt keine Begrenzung. - Verzögerung (ms) legt eine einmalige Pause ein, bevor die Anfrage Cache oder Origin erreicht, gedeckelt bei 5000 ms. Der Hebel gegen Bots mit vielen kleinen Anfragen, bei denen ein winziger Antwortkörper jede Ratenbegrenzung wirkungslos macht.
Mindestens einer der beiden Werte muss ungleich null sein. Drosseln mehrere Quellen dieselbe Anfrage, setzt sich die stärkste durch: die größte Verzögerung und die kleinste Rate ungleich null.
Überspringen
Überspringen nimmt eine Anfrage vom Rest der WAF-Regelliste aus — auch von den verwalteten Regeln von Smoxy, die sonst greifen würden. Eine niedrige Reihenfolge sorgt dafür, dass die Regel zuerst läuft.
Die vorgelagerten Sicherheitsstufen macht sie nicht rückgängig. Reputationsverdikte, Under Attack Mode und die IP-Listen sind bereits angewandt, wenn die Engine läuft; um eine Anfrage davon auszunehmen, braucht es eine Access Rule mit Allow oder Skip.
WARNING
Protokollieren ist nicht passiv. Die Aktion hält den Treffer fest und handelt selbst nicht, sie übernimmt aber die Entscheidung — jede spätere Regel, die blockiert hätte, kommt damit nicht mehr zum Zug, und auch die Anomalie-Schwelle bleibt außen vor.
Für passives Beobachten, das späteren Regeln den Vortritt lässt, eignet sich Score mit dem Wert 0. Der Treffer wird trotzdem festgehalten und bleibt im Traffic-Log sichtbar.
Wie über eine Anfrage entschieden wird
Über das Ergebnis entscheidet die Reihenfolge, nicht die Schwere. Eine Challenge mit Reihenfolge 10 schlägt eine Blockade mit Reihenfolge 20.
- Die eigenen Regeln und die von Smoxy verwalteten Regeln werden zu einer Liste zusammengeführt und aufsteigend nach Reihenfolge sortiert.
- Jede Regel wird der Reihe nach ausgewertet. Deaktivierte Regeln werden übersprungen.
- Bei einem Treffer kommt der Score der Regel zur laufenden Summe hinzu — bei jeder Aktion, nicht nur bei
Score. - Die erste zutreffende Regel, deren Aktion nicht
Scoreist, übernimmt den einen Entscheidungsplatz. Spätere Regeln dürfen weiterhin Score beisteuern, die Entscheidung aber nicht mehr ändern. - Hat nach der Liste nichts die Entscheidung übernommen und die angesammelte Summe 5 erreicht, wird die Anfrage blockiert.
- Das Verdikt wird bei jeder Anfrage festgehalten, ob getroffen oder nicht — siehe Prüfen, ob eine Regel gegriffen hat.
Kurz: genau eine Regel entscheidet. Alles andere steuert Score bei oder kommt zu spät.
Von Smoxy verwaltete Regeln
Regeln unter Von Smoxy verwaltete Regeln stammen von smoxy, werden dort gepflegt und gelten plattformweit — etwa gegen das Absuchen nach Konfigurationsdateien, gegen Tor-Exit-Knoten oder gegen zu aggressive Crawler. Bearbeiten lassen sie sich nicht; über den Schalter in der Zeile lässt sich jede einzelne für die eigene Zone ein- oder ausschalten.
Die Kennzeichnungen in der Zeile zeigen, wie eine Regel die Zone erreicht:
- Verwaltet — die Regel gehört smoxy, nicht der Zone.
- Opt-in — die Regel ist für die Zone aus, bis sie eingeschaltet wird. Regeln ohne diese Kennzeichnung sind standardmäßig an und bleiben es, bis sie ausgeschaltet werden.
Eine ausdrückliche Entscheidung schlägt immer den Standard und bleibt erhalten: Ändert smoxy später den Standard einer Regel, behält eine Zone, die sich schon festgelegt hat, ihre Wahl.
Eine verwaltete Regel ausschalten
Den Schalter der Zeile umlegen. Die Regel greift für die Zone sofort nicht mehr — sie blockiert nicht, prüft nicht per Challenge, drosselt nicht und fließt auch nicht mehr in die Anomalie-Schwelle ein.
Ausgewertet wird sie weiterhin. Eine für die Zone ausgeschaltete Regel fließt in einen getrennten Shadow-Score ein, der im Traffic-Log als waf_rule_action = shadow auftaucht. So bleibt sichtbar, ob sie gegriffen hätte — und ein Opt-out lässt sich anhand von Belegen zurücknehmen statt nach Gefühl.
TIP
Verwaltete Regeln bleiben am besten an, solange nicht nachweislich eine davon Fehlalarme für die eigene Anwendung auslöst. Im Zweifel zuerst ins Traffic-Log schauen oder den Support fragen.
Prüfen, ob eine Regel gegriffen hat
Jede Anfrage trägt das Verdikt der Regel-Engine, ob etwas getroffen hat oder nicht. Die Werte stehen im Traffic-Log der Zone und stehen als Antwort-Header zur Verfügung, sobald die Debug-Header für die Zone aktiv sind.
| Antwort-Header | Feld im Traffic-Log | Bedeutung |
|---|---|---|
s-waf-rule | waf_rule | Die ID der Regel, die entschieden hat, oder score, wenn die Anomalie-Schwelle ausgelöst hat. |
s-waf-rule-action | waf_rule_action | block, challenge, throttle, skip, log oder shadow. |
s-waf-rule-score | waf_rule_score | Der Anomalie-Score der Anfrage, einschließlich des Shadow-Scores nicht durchgesetzter Regeln. |
WARNING
Zwei Verdikte, ähnliche Namen. waf_action und waf_score gehören nicht zur Regel-Engine — sie tragen das IP-Reputationsverdikt der verwalteten Szenarien. Eine von einer eigenen WAF-Regel blockierte Anfrage zeigt regelmäßig waf_action: allow direkt neben waf_rule_action: block.
Bei der Untersuchung einer WAF-Regel zählt waf_rule_action.
s-allowlist erzählt die umgekehrte Geschichte: Der Wert benennt die Vertrauensliste, die eine Anfrage komplett an der Engine vorbeigeführt hat (global, tenant oder verified_bot). Bleibt eine erwartete Regel wirkungslos, lohnt hier der erste Blick.
Beispiele
Beispiel 1: eine Dateisuche, versteckt in einem Tracking-Parameter
Aus dem laufenden Betrieb. Eine Anfrage sah aus wie eine gewöhnliche Produktseite:
/fahrrad-bekleidung/…/castelli-espresso-2-w-radtrikot-kurzarm-damen-kaufen.html
?srsltid=AfmBOoovzZW4ddo…jwWUE/.env.developmentAn einen echten Google-Parameter srsltid war hinten eine Suche nach .env angehängt. Das Ziel uri hätte das nicht gesehen — uri endet vor dem ?. Genau dafür gibt es uri.raw.
Beschreibung: Suche nach Umgebungs- und Konfigurationsdateien blockieren
Übereinstimmung: Beliebige Bedingung
Reihenfolge: 10
Bedingung: Ziele uri.raw
Transformationen urlDecode, lowercase
Operator Entspricht einer Phrase
Muster .env .git/config wp-config.php .aws/credentials id_rsa
Aktion: BlockierenBeispiel 2: SQL-Injection, ohne Regex
SQL-Injection erkennen braucht kein Muster — der Operator lässt einen eigens dafür gebauten Detektor über jeden Wert laufen.
Beschreibung: SQL-Injection in Query und Formulardaten blockieren
Übereinstimmung: Beliebige Bedingung
Reihenfolge: 20
Bedingung 1: Ziele args, body.form
Transformationen urlDecode, removeNulls
Operator SQL-Injection erkennen
Bedingung 2: Ziele body.json
Transformationen removeNulls
Operator SQL-Injection erkennen
Aktion: BlockierenBeispiel 3: verdächtige Automatisierung bewerten statt blockieren
Keines der beiden Signale rechtfertigt für sich eine Blockade. Zusammen mit allem Weiteren, was Score liefert, reißen sie die Schwelle.
Beschreibung: Anomalie-Score für Skript-Clients erhöhen
Übereinstimmung: Beliebige Bedingung
Reihenfolge: 200
Bedingung 1: Ziele headers.user-agent
Transformationen lowercase
Operator Entspricht einer Phrase
Muster curl wget python-requests go-http-client libwww-perl
Bedingung 2: Ziele headers.user-agent
Operator Entspricht Regex
Muster ^$
Aktion: Score
Score: 3Beispiel 4: einen Scraper bremsen, ohne ihn zu blockieren
Beschreibung: Massenhaftes Abgrasen des Katalogs drosseln
Übereinstimmung: Alle Bedingungen
Reihenfolge: 50
Bedingung 1: Ziele uri
Operator Beginnt mit
Muster /catalog/
Bedingung 2: Ziele geoip.asn
Operator Ist in Menge enthalten
Muster 14061, 16509, 24940
Aktion: Drosseln
Rate: 65536
Verzögerung: 250Die ASNs von Hosting-Anbietern sind für einen Shop-Katalog ein starkes Signal: Echte Kundschaft stöbert selten aus einem Rechenzentrum.
Beispiel 5: einen Endpunkt ausnehmen, der die Regeln auslöst
Ein Webhook-Empfänger mit ungewöhnlichen Nutzdaten kann aussehen wie ein Angriff. Eine niedrige Reihenfolge stellt sicher, dass die Ausnahme vor allem anderen läuft.
Beschreibung: WAF-Regeln für den Zahlungs-Webhook überspringen
Übereinstimmung: Alle Bedingungen
Reihenfolge: 0
Bedingung 1: Ziele uri
Transformationen normalizePath, lowercase
Operator Gleich (Zeichenkette)
Muster /webhooks/payment
Bedingung 2: Ziele ip
Operator IP entspricht
Muster 203.0.113.0/24
Aktion: ÜberspringenDer Pfad gehört mit einer Herkunftsprüfung zusammen. Eine skip-Regel allein auf dem Pfad ist eine offene Tür mit der eigenen Adresse daran.
Beispiel 6: einen verwundbaren Endpunkt sperren, bis der Patch steht
Ein virtueller Patch verschafft die Zeit, den echten Fix auszurollen.
Beschreibung: CVE-2026-31887 — Durchprobieren von Bestellcodes blockieren
Übereinstimmung: Alle Bedingungen
Reihenfolge: 5
Bedingung 1: Ziele uri
Transformationen urlDecode, normalizePath, lowercase
Operator Beginnt mit
Muster /store-api/order
Bedingung 2: Ziele method
Operator Gleich (Zeichenkette)
Muster POST
Bedingung 3: Ziele body.json
Operator Entspricht Regex
Muster ^[a-f0-9]{32}$
Aktion: BlockierenRegeln über die API verwalten
Jedes Feld des Editors steht auch über die API zur Verfügung, dazu einige, die die Oberfläche nicht zeigt.
| Methode | Endpunkt | Zweck |
|---|---|---|
GET | /api/zones/{zoneId}/security/waf-rules | Eigene Regeln der Zone auflisten |
POST | /api/zones/{zoneId}/security/waf-rules | Regel anlegen |
GET | /api/zones/{zoneId}/security/waf-rules/{id} | Eine Regel lesen |
PATCH | /api/zones/{zoneId}/security/waf-rules/{id} | Regel ändern |
DELETE | /api/zones/{zoneId}/security/waf-rules/{id} | Regel löschen |
GET | /api/zones/{zoneId}/security/global-waf-rules | Die für die Zone geltenden verwalteten Regeln auflisten |
PATCH | /api/zones/{zoneId}/security/global-waf-rules/{id} | Eine verwaltete Regel für die Zone ein- oder ausschalten |
Die Regel für Skript-Clients aus Beispiel 3 anlegen:
curl -X POST "https://api.smoxy.eu/api/zones/412/security/waf-rules" \
-H "Authorization: Bearer $SMOXY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"description": "Anomalie-Score für Skript-Clients erhöhen",
"enabled": true,
"phase": "request",
"order": 200,
"match": "any",
"conditions": [
{
"targets": ["headers.user-agent"],
"transforms": ["lowercase"],
"operator": "pm",
"pattern": "curl wget python-requests go-http-client libwww-perl"
},
{
"targets": ["headers.user-agent"],
"operator": "rx",
"pattern": "^$"
}
],
"action": "score",
"score": 3
}'Eine verwaltete Regel für eine Zone ausschalten:
curl -X PATCH "https://api.smoxy.eu/api/zones/412/security/global-waf-rules/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer $SMOXY_TOKEN" \
-H "Content-Type: application/merge-patch+json" \
-d '{"enabledForZone": false}'Zur Authentifizierung siehe API-Token.
Felder, die die Oberfläche nicht zeigt
| Feld | Wirkung |
|---|---|
stop | Beendet die Regelauswertung vollständig, sobald die Regel greift — spätere Regeln steuern nicht einmal mehr Score bei. Bei verwalteten Regeln, die für die Zone aus sind, ohne Wirkung. |
expression | Ein Notausgang für Logik, die die Bedingungsliste nicht abbildet, in derselben Ausdruckssprache wie bei den Access Rules. Wird nur ausgewertet, wenn conditions leer ist. |
Validierung
Die API weist eine Regel zurück, die eine dieser Vorgaben verletzt:
- Mindestens eine Bedingung oder eine
expression. - Jede Bedingung hat ein nicht leeres
targets-Array und einen bekanntenoperator. - Jeder Operator außer
detectSQLiunddetectXSShat ein nicht leerespattern. action: blockträgt einenstatuszwischen 100 und 599.action: throttleträgt einrateBpsund/oderdelayMsungleich null.- Ziele und Transformationen stammen aus den Listen auf dieser Seite.
Gut zu wissen
- Es entscheidet die Reihenfolge, nicht die Schwere. Die erste zutreffende Regel, die nicht
Scoreist, gewinnt. Ausnahmen gehören an den Anfang des Zahlenbereichs, Blockaden dahinter, und jede Regel bekommt eine eigene Zahl. ProtokollierenundÜberspringenlegen spätere Regeln still. NurScoreist passiv.- Regex achtet auf Groß-/Kleinschreibung, solange nicht
(?i)oderlowercaseetwas anderes vorgibt. - Erst dekodieren, dann vergleichen. Eine Regel ohne Transformationen ist ein
%2e%2e%2fdavon entfernt, nutzlos zu sein. uriist normalisiert,uri.rawnicht. Bei der Suche nach eingeschmuggelten Nutzlasten gehören beide geprüft.- Körper über 256 KB werden nicht geprüft. Bei
GETebenso wenig. - Eine Regel kann keine frühere Entscheidung aufheben. Adressen auf der Allowlist, verifizierte Crawler und Ausnahmen per Access Rule erreichen die Engine gar nicht.
- Blockaden antworten mit
403. Die Seite dazu lässt sich unter Benutzerdefinierte Seiten gestalten. - Neue Regeln zuerst mit
Score: 0fahren. Eine neue Regel passiv ausrollen, einen Tag langwaf_ruleim Traffic-Log beobachten und sie danach auf die gewünschte Aktion umstellen.
Weiterführend
- Sicherheit & WAF — die umgebende Sicherheitsschicht
- Access Rules — die frühere, gröbere Richtlinienebene
- Threat Lookup — eine einzelne Adresse untersuchen
- Lebenszyklus einer Anfrage — wo welche Stufe läuft
