Quellcode: github.com/Alex0176/odoo-web-rbl — AGPL-3, frei verwendbar.
Wer einen Odoo-Server im Internet betreibt, bekommt Besuch. Nicht gelegentlich, sondern ununterbrochen. Über siebzehn Tage haben wir auf unseren fünf Webseiten 731.297 Anfragen mitgeschrieben und ausgewertet. 110.511 davon waren keine Besucher, sondern automatisierte Suche nach Schwachstellen, Zugangsdaten und Konfigurationsdateien.
Dieser Beitrag beschreibt Web RBL, ein Open-Source-Modul für Odoo 19 Community, das diesen Verkehr erkennt, bewertet, verbucht und abweist — und das die Sperrliste als RBL-Liste veröffentlicht, also in dem Format, das Firewalls und Reverse Proxys unmittelbar lesen. Alle Zahlen stammen aus dem Echtbetrieb.
Was das Modul kann — die Funktionen im Überblick
| Funktion | Was sie tut | Auslieferung |
|---|---|---|
| Mustererkennung | Erkennt Sondierungen an Pfad und Endung: .env, .git, Konfigurationsdateien, Cloud-Schlüssel, CI/CD-Bauanweisungen, WordPress, PHP, Pfad-Traversal, Datenbankverwalter, GraphQL, Befehlsausführung über /api/fs/exec und ähnliche Schnittstellen | sperren |
| Drei Stufen je Muster | sperren, zählen oder melden — je Muster umstellbar, ohne Code | je Muster |
| Schwellen | So viele Treffer desselben Musters, bevor gesperrt wird; für Anmeldungen zehn | 10 bei Anmeldung |
| Anmeldeabwehr | Gescheiterte Anmeldungen über Maske und XML-RPC/JSON-RPC, gescheiterte Sitzungsprüfungen, Zugriffe auf den Datenbankverwalter — in der Datenbank, nicht im Arbeitsspeicher | an |
| Bot-Erkennung an der Anmeldung | Wer die Wartemeldung nach zehn Fehlversuchen ignoriert und weiterklopft, wird sofort gesperrt | sperren |
| Verhaltenserkennung | Adressen, die in fünf Minuten zwanzig Fehlseiten und kaum eine Trefferseite erzeugen — also raten statt lesen | melden |
| Bewertung 0–100 | Wie sicher ist es, dass hinter der Adresse ein Angreifer steht? Aus Schwere des Musters, Zahl verschiedener Muster, auffälligen Tagen, betroffenen Domains und Trefferzahl — mit Begründung im Klartext | an |
| Anmeldesperre nach Bewertung | Ab einer einstellbaren Bewertung ist die Anmeldung verboten, die Webseite bleibt lesbar | ab 40 |
| Verdacht auf gestohlene Zugangsdaten | Eine gelungene Anmeldung von einer auffälligen Adresse wird gemeldet und auf Wunsch als Aufgabe zugewiesen — einmal je Adresse und Tag | an |
| Bedrohungslisten | Tor-Ausgangsknoten, Spamhaus DROP, FireHOL Level 1, blocklist.de vorkonfiguriert; jede weitere RBL-Liste per Adresse eintragbar, täglicher Abgleich, je Liste eigene Stufe | melden |
| Kein Zugang zur Anmeldung | Die vierte Stufe für Listen und Länder: Webseite lesbar, Anmeldemaske und Schnittstellen zu — die passende Antwort auf Tor | Option |
| Herkunftsland | Land je Treffer und Adresse über GeoLite2; die Datenbank führt das Modul mit einem kostenlosen Lizenzschlüssel selbst nach | anzeigen |
| Länderregeln | Sperren, kein Zugang zur Anmeldung, melden oder ausdrücklich frei — je Land, bewusst ohne Vorgabe | keine |
| Fehlkonfigurationen | QNAP, Synology, Exchange-Autodiscover, ActiveSync, WebDAV/CalDAV/CardDAV werden erkannt, nie gesperrt und mit Befund und betroffener Domain in eine Arbeitsliste gestellt | melden |
| Ticket je Adresse | Aus einem Befund wird auf Wunsch ein Ticket — genau eines je Adresse, ein geschlossenes wird wieder geöffnet statt verdoppelt | aus |
| Pflichtseiten und Sammler | Der kanonische Impressumspfad bleibt immer erreichbar; maschinelles Durchprobieren fremder Schreibweisen wird erkannt und auf Wunsch gesperrt | melden |
| Freiliste | Adressen und Netze, die nie gesperrt werden; füllt sich täglich aus der Firewall (VPN-Gegenstellen) und aus den veröffentlichten Adressbereichen von Googlebot und Bingbot | an |
| Kundenzuordnung | Ein Treffer aus dem Netz eines Kunden wird ihm zugeordnet — aus der Freiliste, nie von Hand geraten | an |
| Domain und Kennung je Treffer | Welche Webseite wurde angesprochen, mit welchem User-Agent — beides fehlt im Zugriffsprotokoll | an |
| Auswertung | Diagramm und Pivot über alle Treffer: je Muster, Tag, Domain, Land, Adresse | an |
| Köder | Sonden bekommen erfundene Antworten mit Kanarienwert; wer ihn später abruft, hat sie gelesen | aus |
| RBL-Auslieferung | Die Sperrliste als reine Adressliste oder JSON unter einer eigenen, mit Token geschützten Adresse — für HAProxy, OPNsense und jede Firewall, die URL-Listen liest | an |
Alles, was mit melden, aus oder Option ausgeliefert wird, ist bewusst so: Wer eine Sperre scharf schaltet, soll es tun, weil er ein paar Tage zugesehen hat, wer darauf fällt — nicht, weil die Vorgabe es so wollte.
Die Auswertung: Treffer je Muster über sieben Tage. Der höchste Balken ist die Suche nach .env-Dateien.
RBL-Listen: ein standardisierter Weg, Sperren auszuliefern
RBL steht für Real-time Blackhole List. Der Begriff stammt aus der Mailwelt, wo Spamhaus und andere seit den Neunzigern Listen bösartiger Absenderadressen veröffentlichen. Das Prinzip ist denkbar einfach und genau deshalb so verbreitet: eine Adresse je Zeile, über HTTP abrufbar, regelmäßig neu geladen. Kein Format, das man erst parsen muss, keine Schnittstelle, für die man ein Werkzeug braucht.
Praktisch jede Firewall und jeder Reverse Proxy kann eine solche Liste einlesen und daraus Regeln bauen. Die Hersteller nennen das unterschiedlich, der Mechanismus ist überall derselbe:
- OPNsense und pfSense — URL Table Alias: Adressliste per HTTP laden, als Alias in Firewallregeln verwenden, Aktualisierung im Stunden- oder Tagesrhythmus
- HAProxy — ACL-Dateien und Maps:
src -f sperrliste.txtin einerhttp-request deny-Regel, nachladbar über die Laufzeit-API ohne Neustart - nginx — geo-Modul mit eingebundener Adressdatei, oder
deny-Anweisungen aus einer generierteninclude-Datei - Fortinet FortiGate — External Block List bzw. Threat Feed: eine URL, aus der die Firewall eine IP-Liste bezieht und in Richtlinien verwendet
- Palo Alto Networks — External Dynamic List (EDL): dasselbe Prinzip, als eigener Objekttyp in den Sicherheitsrichtlinien
- Check Point — Custom Intelligence Feeds und IP Block Lists über eine URL
- Cisco Secure Firewall (Firepower) — Security Intelligence Feeds mit eigenen Listenquellen
- Sophos Firewall — Third-Party Threat Feeds: Adresslisten von einer URL als Quelle für Blockregeln
- Juniper SRX — Dynamic Address Entries aus Feeds
- MikroTik RouterOS — Address Lists, per Skript und
fetchaus einer URL befüllt - CrowdSec — eigene Listen als Quelle für die Bouncer auf jedem unterstützten System
Genau in diesem Format liefert Web RBL seine Sperrliste aus. Die Firewall verwirft die Pakete, bevor sie den Webserver erreichen — und mit ihnen jeden anderen Versuch derselben Adresse, etwa auf den Mailserver oder das VPN-Gateway.
Beide Richtungen, aber die richtige Stelle
Der Weg funktioniert auch umgekehrt: In Web RBL lässt sich jede beliebige RBL-Liste eintragen — eine URL, eine Stufe, fertig. Tor-Ausgangsknoten, Spamhaus DROP, FireHOL und blocklist.de sind vorkonfiguriert, weitere kommen mit drei Klicks dazu. Das Modul zerlegt jede Liste in Adressbereiche und prüft jede Anfrage dagegen, in wenigen Mikrosekunden.
Und doch: Sinnvoller ist es, fremde Listen auf der Firewall davor zu verwenden. Aus drei Gründen. Die Firewall sieht alle Dienste, nicht nur HTTP — eine Adresse von der Spamhaus-Liste soll auch am Mailserver und am VPN scheitern. Sie verwirft auf Paketebene, bevor eine Verbindung überhaupt zustande kommt, und kostet den Anwendungsserver damit nichts. Und sie ist der Ort, an dem solche Listen ohnehin gepflegt werden; eine zweite Kopie in der Anwendung ist eine zweite Stelle, die veralten kann.
Wofür die Listen im Modul dann noch gut sind: für das, was eine Firewall nicht kann. Sie kennt keine Anmeldemaske. Web RBL kann einer Adresse von der Tor-Liste den Zugang zur Anmeldung verweigern und die Webseite trotzdem ausliefern — wer anonym lesen will, soll das dürfen; wer anonym Kennwörter durchprobieren will, nicht. Und es kann eine gelungene Anmeldung von einer gelisteten Adresse als Verdachtsfall melden. Beides braucht die Liste dort, wo die Anmeldung stattfindet.
Bewertung statt Bauchgefühl
Eine Adresse, die einmal nach /wp-login.php gefragt hat,
ist etwas anderes als eine, die an zwei Tagen mit fünf verschiedenen
Mustern über drei Domains gegangen ist. Web RBL rechnet das in eine
Bewertung von 0 bis 100 um — aus dem, was es selbst
gesehen hat, ohne fremden Dienst und ohne Abfrage nach außen.
Ein Eintrag: 99 Treffer, Bewertung 84, und die Begründung im Klartext — schwerstes Muster, fünf verschiedene ernste Muster, zwei auffällige Tage, über zwanzig Treffer.
Die Bewertung entscheidet über zwei Dinge. Ab einem einstellbaren Wert ist die Anmeldung verboten — die Webseite bleibt lesbar, aber wer schon nach Zugangsdaten gesucht hat, bekommt keine Gelegenheit, gefundene auszuprobieren. Und eine gelungene Anmeldung von einer Adresse mit Bewertung wird gemeldet: Dann hat jemand nicht mehr geraten, sondern gewusst. Entweder war der berechtigte Benutzer unterwegs, oder die Zugangsdaten sind abhandengekommen — das Modul entscheidet das nicht, es legt es jemandem vor, der nachfragen kann. Das Kennwort selbst wird dabei nirgends berührt.
Die Sperrliste, gefiltert nach Bewertung ab 40: Trefferzahl, auffällige Tage, betroffene Domains und der letzte Pfad je Adresse.
Was Web RBL schützt — die Schutzwirkung im Einzelnen
1. Zugangsdaten bleiben unentdeckt
Die größte gemessene Angriffsklasse sucht nicht nach Lücken in Odoo, sondern nach liegengebliebenen Geheimnissen. Über siebzehn Tage:
- 57.721 Anfragen nach
.env-Dateien — dort stehen Datenbankkennwörter, API-Schlüssel und Sitzungsgeheimnisse - 5.535 Anfragen nach Konfigurationsdateien
- 4.388 Anfragen nach Cloud-Zugangsdaten:
credentials.json,service-account.json,firebase-adminsdk.json,rclone.conf,.git-credentials - 2.811 Anfragen nach
.git-Verzeichnissen — wer eines findet, lädt den vollständigen Quellcode samt Historie herunter - 1.907 Anfragen nach Bauanweisungen wie
.github/workflows/deploy.ymloder.gitlab-ci.yml, in denen Registraturen und Schlüsselnamen stehen
Entscheidend ist dabei nicht die Zahl der Anfragen, sondern die Zahl
der verschiedenen Adressen: /credentials.json kam
von 98 Adressen, /.git-credentials von 92. Das ist kein
einzelner Scanner, sondern ein Standardrepertoire, das weltweit
gleichzeitig läuft.
2. Anmeldeversuche laufen ins Leere — dauerhaft
Odoo bringt eine eigene Bremse gegen das Durchprobieren von Kennwörtern mit. Sie hat drei Grenzen, die im Odoo-Quelltext selbst dokumentiert sind: Der Zähler liegt im Arbeitsspeicher des Arbeitsprozesses und wird bei jedem Neustart zurückgesetzt, er verzögert nur statt zu sperren, und er zählt ausschließlich Versuche, die bis zur Kennwortprüfung durchkommen.
Web RBL setzt an denselben Stellen an, schreibt aber in die Datenbank. Damit gilt:
- Der Stand überlebt jeden Neustart und gilt über alle Arbeitsprozesse hinweg
- Erfasst werden beide Wege: die Anmeldemaske
/web/loginund die Schnittstellen/xmlrpc/2/commonund/jsonrpc - Erfasst werden auch Versuche, die nie bis zur Kennwortprüfung gelangen — etwa Anmeldungen ohne gültiges Sitzungsmerkmal
- Ein gescheiterter Zugriff auf den Datenbankverwalter wird mitgezählt; das ist der schwerwiegendste Anmeldeversuch überhaupt
Die Schwelle für Anmeldungen steht auf zehn, und der Grund ist eine Messung: Von neun gescheiterten Anmeldungen in siebzehn Tagen stammte die Mehrzahl von Kunden, die sich den Zugang selbst auf einem weiteren Gerät einrichteten und dabei die falsche Domain eintrugen — in einem Fall die eigene, nur mit Bindestrich statt Punkt. Eine Sperre beim ersten Fehlversuch hätte damit nicht Angreifer getroffen, sondern Kunden bei der Einrichtung.
Wer dagegen weiterklopft, obwohl der Server bereits „bitte kurz warten" geantwortet hat, wird sofort gesperrt. Diese Meldung liest ein Mensch und wartet; wer sie ignoriert, ist ein Programm. Ein eigenes Muster mit Schwelle null fängt genau diesen Fall ab, und es kann keinen Kollegen treffen: Dorthin gelangt nur, wer bereits zehn Fehlversuche hinter sich hat und danach weitermacht.
3. Der Angriff kostet den Server nichts mehr
Eine Sonde auf einen Pfad wie /@fs/../../.env war vor
dem Modul teuer: Odoo sucht die Fehlerseite, rendert sie, stolpert
beim Aufbau der Adresse über die Punkt-Segmente und scheitert
daraufhin auch an der Fehlerseite der Fehlerseite. Zwei
Stapelprotokolle je Sonde. Gemessen wurden 28.401 solcher Fehler
in siebzehn Tagen, dazu 9.467 Folgefehler.
Web RBL greift in ir.http._match, also vor der
Wegfindung. Die Antwort fällt ohne Vorlage, ohne Datenbankzugriff
über die Sperrprüfung hinaus und ohne Protokollzeile. Die Prüfung
gegen Freiliste, Bedrohungslisten und Länderregeln läuft aus dem
Zwischenspeicher über sortierte Adressbereiche — wenige
Mikrosekunden, auch bei über dreißigtausend Bereichen.
4. Die Firewall wirft den Angreifer hinaus, bevor er ankommt
Die Sperrliste wird als RBL-Liste veröffentlicht, die HAProxy und OPNsense unmittelbar lesen. Der Angreifer erreicht den Webserver damit gar nicht mehr — und auch keinen anderen Dienst auf demselben Host. Ein einmal als bösartig erkannter Zugriff schützt so rückwirkend die gesamte Maschine.
Drei Stufen: sperren, zählen, melden
Nicht jede Anfrage ins Leere ist ein Angriff. Web RBL unterscheidet deshalb drei Stufen, und die Stufe lässt sich je Muster umstellen, ohne den Code anzufassen.
| Stufe | Die auslösende Anfrage | Folge für die Adresse |
|---|---|---|
| sperren | wird abgewiesen | 24 Stunden gesperrt, nach drei auffälligen Tagen dauerhaft |
| zählen | läuft durch | nur verbucht, keine Sperre |
| melden | läuft durch | verbucht mit Befundtext, wird nie gesperrt |
Für Bedrohungslisten und Länder gibt es eine vierte: kein Zugang zur Anmeldung. Die Webseite bleibt lesbar, Anmeldemaske und Schnittstellen sind zu. Das ist der Mittelweg für alles, was verdächtig ist, aber nicht bösartig sein muss — Tor, ein Rechenzentrumsbereich, ein Land ohne Kunden.
Welche Angriffe erkannt werden
Alle Muster sind gegen echten Verkehr geprüft. Die Zahl der verschiedenen Adressen steht bewusst daneben — sie zeigt, ob ein Muster einen einzelnen Scanner trifft oder ein verbreitetes Vorgehen.
| Angriffsklasse | Anfragen | Adressen |
|---|---|---|
.env-Abgriff | 57.721 | 223 |
| PHP-Sonden | 12.237 | 256 |
| Pfad-Traversal mit lohnendem Ziel | 10.046 | 64 |
| Konfigurationsdateien | 5.535 | 114 |
| Cloud-Zugangsschlüssel | 4.388 | 152 |
| WordPress-Sonden | 3.366 | 385 |
.git-Abgriff | 2.811 | 255 |
| Odoo-Erkundung (Datenbankverwalter, Versionsabfrage) | 2.500 | 213 |
KI-Werkzeugketten und Befehlsausführung (/mcp, /api/fs/exec) | 2.450 | 74 |
| Bauanweisungen (CI/CD) | 1.907 | 88 |
| GraphQL-Endpunkte | 1.878 | 71 |
Bemerkenswert ist die jüngste Klasse. /api/fs/exec
wurde 369 mal von 54 verschiedenen Adressen angefragt — das ist
kein Lesezugriff, sondern der Versuch, Befehle auszuführen. Solche
Ziele gab es vor zwei Jahren nicht; sie stammen aus Schnittstellen
neuer KI-Werkzeuge und Aufgabenwarteschlangen. Wer seine Abwehr nur
auf WordPress und PHP ausrichtet, sieht davon nichts. In der
Bewertung wiegt diese Klasse entsprechend schwer.
Bedrohungslisten und Herkunftsland
Vier Listen, 32.851 Adressbereiche, alle auf „nur melden". Jede weitere Liste ist eine Adresse und eine Stufe.
Eine fremde Liste ist eine Behauptung, die jemand anderes
aufstellt, aus Gründen, die wir nicht kennen, über Verkehr, den wir
nie gesehen haben. Sie kann falsch sein, veraltet oder für einen
anderen Zweck gedacht: blocklist.de sammelt vor allem
Adressen, die anderswo SSH-Anmeldungen durchprobiert haben, und das
sagt über einen Webserver wenig. Deshalb führt Web RBL fremde Listen
getrennt von der eigenen Sperrliste, und deshalb ist die Vorgabe
melden. Und die eigene Freiliste gewinnt immer: Ein Kunde, den
wir kennen, wiegt schwerer als die Einschätzung eines Dritten.
Das Herkunftsland steht an jedem Treffer und jeder Adresse. Zum Beurteilen ist es unersetzlich — ein Anmeldeversuch aus dem eigenen Land um zehn Uhr vormittags ist etwas anderes als einer aus einem Land ohne einen einzigen Kunden. Zum pauschalen Aussperren taugt es wenig, und das sagen die eigenen Zahlen: Die Angreifer in unserer Liste kamen überwiegend aus Cloud-Bereichen in Belgien, Finnland und den Niederlanden. Eine Sperre für alles außerhalb des deutschsprachigen Raums hätte sie nicht getroffen — dafür aber eigene Mitarbeiter im Urlaub und Kunden auf Geschäftsreise.
Länderregeln werden leer ausgeliefert, und die Ansicht sagt, warum.
Fehlkonfigurationen melden statt sperren
Der häufigste Fall im Echtverkehr ist weder Angriff noch Besucher, sondern defekte Software, die den Webserver für etwas anderes hält:
- 1.367 Aufrufe der Web-Schnittstelle eines QNAP-NAS — ein Sync-Client, dessen Ziel nicht mehr stimmt. Ein einziger Anschluss klopfte 962 mal an.
- 65 Autodiscover-Abfragen — ein Outlook, das die Webdomain für seinen Exchange hält
Solche Adressen werden nie gesperrt. Eine Sperre behebt den Defekt nicht, sie verbirgt ihn — und trifft denjenigen, dessen Gerät ohnehin schon falsch eingestellt ist. Stattdessen entsteht ein Eintrag mit Befundtext und den betroffenen Domains, aus dem auf Wunsch automatisch ein Ticket wird: je Adresse genau eines, und wird es geschlossen und die Adresse fällt erneut auf, öffnet sich dasselbe Ticket wieder, statt dass ein zweites entsteht.
Erkannt werden QNAP, Synology, Exchange-Autodiscover, ActiveSync
sowie WebDAV-, CalDAV- und CardDAV-Clients. Die Muster nennen dabei
exakte Dateinamen und Verzeichnisse, niemals bloße Endungen:
Im selben Verzeichnis /cgi-bin/ liegen die harmlosen
Sync-Aufrufe direkt neben klassischen Sonden wie
printenv.pl.
Die Freiliste: Adressen, die nie gesperrt werden
Der Preis eines Irrtums ist nicht bei allen Adressen gleich. Bei einem Scanner aus einem Rechenzentrum kostet ein Fehlalarm nichts. Bei der Gegenstelle eines Standorttunnels kostet er den Standort.
Deshalb gibt es eine zweite Liste, die vor der ersten steht: Adressen und Netze, die nie gesperrt werden. Sie schaltet dabei nichts stumm — wer darauf steht, wird weiterhin geprüft und verbucht, nur die Folge entfällt. Das ist der Unterschied zu einer Ausnahme in der Firewall: Die macht blind, diese macht nur geduldig.
Gefüllt wird sie täglich aus zwei Quellen: aus der Firewall selbst mit allen VPN-Gegenstellen, damit ein neu eingerichteter Tunnel nicht darauf angewiesen ist, dass jemand an die Sperrliste denkt — und aus den veröffentlichten Adressbereichen von Google und Microsoft für ihre Crawler. Nur so lässt sich ein echter Googlebot von einem Scanner unterscheiden, der sich so nennt. Suchmaschinen dürfen nie gesperrt werden; wer sie aussperrt, nimmt seine Seite ohne Weg zurück aus der Indexierung.
Dabei gilt eine Regel, die wichtiger ist als der Abgleich: Eine leere Antwort löscht nie. Antwortet die Quelle nicht, leer oder unverständlich, bleibt die Liste unverändert. Eine Freiliste, die sich bei einer Störung selbst leert, nimmt im schlechtesten denkbaren Moment alle Tunnel mit.
Trägt ein Freilisten-Eintrag einen Kunden, wird jeder Treffer aus seinem Netz ihm zugeordnet. Eine Fehlkonfiguration hat damit sofort einen Ansprechpartner, ohne dass jemand Adressen nachschlagen muss.
Pflichtangaben und automatisierte Datensammler
Das Impressum ist keine gewöhnliche Seite. Es muss für Menschen erreichbar bleiben, denn eine Sperre darauf schafft genau den Verstoß, den ein Sammler sucht. Zugleich ist es die Seite, auf der Name und Anschrift stehen — und damit das Ziel maschineller Ernte.
Bei der österreichischen Abmahnwelle wegen eingebundener Google-Schriften zeigten die Protokolle, dass die Schreiben nicht aus Einzelbesuchen stammten, sondern aus einem automatisierten Rundumschlag: verschiedene, nicht zusammenhängende Hosts im Abstand von Millisekunden.
Web RBL löst das durch Herabstufung statt Ausnahme. Der
kanonische Pfad /impressum trifft auf gar kein Muster und
bleibt immer erreichbar. Fremde Schreibweisen wie
/impressum.php — die es auf einer Odoo-Seite nicht
geben kann — werden gemeldet, und wer die maschinelle Ernte
nicht hinnehmen will, stellt einen Parameter um.
sitemap und robots sind davon ausgenommen
und grundsätzlich nicht sperrbar: Sie enthalten keine
personenbezogene Angabe, und sie zu holen ist die Aufgabe jedes
Suchmaschinen-Crawlers.
Domain und Kennung: was im Zugriffsprotokoll fehlt
Das Zugriffsprotokoll von werkzeug schreibt weder den angesprochenen Host noch die Kennung des Aufrufers mit. Odoo bekommt beide selbstverständlich — ohne den Host könnte es bei mehreren Webseiten gar nicht die richtige auswählen. Nachlesen kann man es hinterher aber nicht.
Web RBL hält beides je Treffer fest. Das beantwortet zwei Fragen, die sich sonst nicht beantworten lassen: welche Webseite eine Fehlkonfiguration anspricht — und damit, welchem Kunden die Domain gehört — und ob eine Adresse eine Seite besucht oder alle. Mehrere nicht zusammenhängende Domains derselben Adresse sind das Kennzeichen des Rundumschlags, und sie erhöhen die Bewertung.
Wie viel die Kennung ausmacht, zeigte eine Auswertung auf einer
unserer Webseiten: Über siebzig Prozent des gesamten Verkehrs
entfielen dort auf einen einzigen Aufrufer, verteilt über mehr als
hundert Adressen. Ohne die Kennung hätte das wie ein verteilter
Scraper ausgesehen. Es war GPTBot, der Crawler von OpenAI
— er fragte immer wieder nach robots.txt und
verhielt sich vollkommen korrekt.
Die Sicherheitsaspekte im Einzelnen
1. Die Proxy-Erkennung — die gefährlichste Stelle überhaupt
Läuft Odoo hinter einem Reverse Proxy und ist proxy_mode
falsch gesetzt, sieht das Modul bei jeder Anfrage dieselbe Adresse:
die des Proxys. Eine Sperre würde dann alle Besucher gleichzeitig
aussperren.
Deshalb prüft Web RBL vor jeder Sperre, ob die Adressbestimmung
verlässlich ist. Es verlangt proxy_mode zusammen mit
einer Weiterleitungs-Kopfzeile, verweigert die Arbeit, wenn eine
Weiterleitung ohne proxy_mode ankommt, und verweigert sie
ebenso bei mehr als einem Zwischenproxy. Im Zweifel wird nicht
gesperrt.
2. Eigene Netze niemals
Private Adressbereiche, Loopback, Link-Local und CGNAT sind fest ausgenommen. Sie können unter keinen Umständen auf der Liste landen, auch nicht von Hand. Dasselbe gilt für fremde Listen: Private und reservierte Bereiche sowie absurd große Netze werden beim Einlesen verworfen.
3. Ein eigener Fehler darf die Webseite nicht mitnehmen
Die gesamte Prüfung läuft in einer Absicherung, die jeden Fehler abfängt. Was hier schiefgeht, wird protokolliert, und die Anfrage läuft unverändert weiter. Ein Schutzmodul, das bei einem eigenen Fehler die Webseite mitnimmt, ist schlimmer als gar keines. Alle Abfragen im Anfrageweg laufen außerdem ohne die Browsersprache des Besuchers und ohne Sortierung nach übersetzten Feldern — ein Besucher mit einer nicht installierten Sprache darf die Prüfung nicht zum Scheitern bringen.
4. Beobachten vor Sperren
Nach der Installation ist das Sperren gelisteter Adressen bei gewöhnlichen Anfragen abgeschaltet. Sonden werden abgewiesen und verbucht, alles andere läuft durch. So lässt sich einige Tage mitlesen, wer tatsächlich auf der Liste landet, bevor jemand ausgesperrt wird. Dasselbe gilt für Verhaltenserkennung, Bedrohungslisten und Länderregeln: melden zuerst, sperren nach Ansehen.
5. Enge Muster statt breiter Netze
Ein falsch erkannter Besucher ist teurer als eine übersehene Sonde.
Jedes Muster trägt deshalb seine Stufe, und sie ist je Muster
umstellbar. Eine Dateiendung allein genügt selten: Bei
.php stehen 14.012 echte Sonden gegen eine Handvoll
Altlinks, bei .asp ist das Verhältnis umgekehrt. Solche
Entscheidungen gehören gemessen, nicht geschätzt.
6. Eine Freigabe von Hand bleibt bestehen
Wer eine Adresse freigibt, hatte einen Grund. Ein weiterer Treffer setzt diese Entscheidung nicht stillschweigend außer Kraft.
7. Die Liste ist geschützt, aber kein Geheimnis
Der Endpunkt verlangt ein Token und antwortet ohne gültiges Token
mit 404, nicht mit 403 — die Existenz
der Adresse wird damit gar nicht erst bestätigt. Der Vergleich läuft
zeitkonstant. Die Liste selbst enthält nichts Vertrauliches: Sie
besteht aus Adressen, die von sich aus bei uns angeklopft haben.
8. Keine Geheimnisse in der Buchhaltung
Bei gescheiterten Anmeldungen wird der versuchte Benutzername vermerkt, niemals das Kennwort. Beim Datenbankverwalter wird aus den übergebenen Werten gar nichts gelesen: Dort steht an vorderster Stelle das Hauptkennwort, und ein Eintrag in einer Sperrliste wandert in jede Datenbanksicherung. Der Lizenzschlüssel für GeoLite2 steht nur im Systemparameter und in keiner Protokollzeile.
9. Der Köder verrät nichts Verwertbares
Optional beantwortet Web RBL Sonden mit erfundenem Inhalt, der einen eindeutigen Kanarienwert enthält. Wer diesen Wert später abruft, hat die gefälschte Antwort gelesen und daraufhin gehandelt — ein Fehlalarm ist dabei ausgeschlossen. Die Köder enthalten keine verwertbaren Angaben, keine echten Pfade und keine gültigen Zugangsdaten. Ausgeliefert wird diese Funktion abgeschaltet, denn sie ändert das Verhalten nach außen sichtbar.
Was das Modul nicht kann
Es ersetzt keine Firewall und keine Web Application Firewall. Es erkennt bekannte Sondierungsmuster in Pfaden, gescheiterte Anmeldungen und auffälliges Verhalten — nicht Angriffe auf Formulare, nicht Einschleusungsversuche in Parameter.
Es sieht außerdem nur, was über HTTP zurückkommt. Was ein Angreifer mit erbeuteten Datenbank- oder Postfachzugängen anstellt, bleibt unsichtbar — und genau deshalb sind die Kanarienwerte Pfade und keine Zugangsdaten.
Und es ersetzt keine Sorgfalt: Ein Modul, das
.env-Sonden abweist, macht eine versehentlich
ausgelieferte .env-Datei nicht ungefährlich.
Verfügbarkeit
Web RBL steht unter der AGPL-3 öffentlich zur Verfügung und läuft bei uns produktiv auf fünf Webseiten:
github.com/Alex0176/odoo-web-rbl
Das Modul setzt Odoo 19 Community voraus und hat keine
Abhängigkeiten außer base und web. Die
Ticketanbindung ist optional und benötigt kein bestimmtes
Ticketsystem; ohne ein solches passiert schlicht nichts. Das
Herkunftsland braucht die kostenlose GeoLite2-Datenbank von MaxMind;
fehlt sie, bleibt das Feld leer und alles andere arbeitet
unverändert.
Weiterführend: Wie Web RBL in eine vollständige Sicherheitsarchitektur passt -- zusammen mit Firewall, Zwei-Faktor-Authentifizierung und Berechtigungen, inklusive Schritt-für-Schritt-Anleitung: Odoo 19 Sicherheitsarchitektur richtig kombinieren.
Fragen, Anmerkungen und Fehlerberichte nehmen wir gerne entgegen — am liebsten als Issue auf GitHub.