Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
stop-bots — Automatisieren Sie das Blockieren bösartiger Bots am Zugriff auf Ihren Server | Kitploit
Tools/GitHubGitHub/ivankovic/stop-bots
DefensivwerkzeugeKonfigurationsprüfungInformationsbeschaffungWebsicherheitNetzwerksicherheitDienstprogramme & FrameworksEinbruchserkennungAnti-BotLog-Analyse
GitHubivankovic/stop-bots

stop-bots

Automatisieren Sie das Blockieren bösartiger Bots am Zugriff auf Ihren Server

12vor 1 TagNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Repository anzeigen
Teilen

Stop Bots

CI crates.io Coverage MSRV License: AGPL v3+

Eine TUI, eine Web-UI und eine CLI, die dir helfen, deinen Server so zu konfigurieren, dass böswillige Bots gestoppt werden, ohne sich hinter einem CDN zu verstecken.

Es arbeitet zusammen mit NGINX und deiner bestehenden Firewall (iptables oder nftables) auf zwei getrennten Ebenen:

  • NGINX-Konfiguration. - Es klassifiziert bekannte Bots nach Kategorie (Scanner, Suchmaschinen, KI-Crawler) und blockiert oder erlaubt sie, indem eine Regel in deine Site-Konfigurationen eingefügt wird. Es durchsucht das NGINX-Log, um Bots dynamisch zu erkennen und sie zu blockieren, selbst wenn noch kein Regelsatz sie erfasst.
  • Ein Firewall-Skript. - Blockiere ganze Länder, IP-Bereiche von Rechenzentren, bekannte Bot-IP-Bereiche oder jede IP-Adresse, die wiederholt erfolglos versucht, sich an deinem Server anzumelden.

Das stop-bots-Dashboard: systemweite Bot-Kategorien, Geo-Blocking, automatische Detektoren und der interne Cron

Die App versucht ihr Bestes, um dich nicht vom Server auszusperren, aber du verwendest sie auf eigenes Risiko. Und beachte, dass sie unter AGPL lizenziert ist. Wenn du sie kommerziell nutzt, stelle sicher, dass du den Wortlaut der Lizenz einhältst.

Installation

Von crates.io:``` cargo install stop-bots

root@kitploit:~
Oder aus einem Checkout erstellen:```
cargo install --path .

Ein vorgefertigtes x86_64-Linux-Binary ist auf den GitHub-Releases verfügbar.

Abhängigkeiten

Erfordert Rust 1.88 oder neuer zum Bauen. In der Praxis nur unter Linux: Es ruft systemctl, nginx -t und nft/iptables auf, sodass es zwar anderswo kompiliert, dort aber kaum nützlich sein wird.

Verwendung

Führe das Binary ohne Argumente aus, um die TUI zu starten, stop-bots web für dieselben Ansichten in einem Browser (siehe Die Web-UI), oder siehe stop-bots --help für die vollständige Liste der CLI-Unterbefehle. TUI und CLI können zusammen verwendet werden. Konfiguriere alles in der TUI und verwende dann die CLI in einem Crontab, um die Regeln aktuell zu halten.

Du kannst die App mit 'q' oder Escape beenden oder aus einem Popup/Untermenü zurückgehen.

Theme

Du kannst mit 't' zwischen dem dunklen und dem hellen Theme wechseln. Die App versucht, das Theme automatisch zu erkennen, aber für einige Terminal- und Multiplexer-Kombinationen sind nicht genügend Informationen verfügbar, um die richtige Wahl zu treffen.

Bildschirme

1–4 (oder d/b/s/p) springen direkt zu einem Bildschirm; Links/Rechts oder ihre vim-Aliase h/l schalten durch sie; ? schaltet jederzeit eine vollständige Tastenbelegungsreferenz um, und : öffnet eine Befehlspalette, die jede Aktion namentlich auflistet. Tab / Shift+Tab wechseln immer zwischen den Panels des aktuellen Bildschirms, niemals zwischen Bildschirmen.

Das Dashboard besitzt alles, was im Firewall-Skript landet; die Site-Einstellungen besitzen alles, was in der NGINX-Konfiguration landet. Diese Aufteilung entscheidet, wo eine bestimmte Einstellung lebt.

  • Dashboard (der Standardbildschirm): systemweite Kategorie-Standardwerte (Scanner / Such-Bots / KI-Bots — erlaubt oder blockiert); hostweites Geo-Blocking (Blockieren oder Allow-List bestimmter Länder); ein Panel „Automatisches Blockieren“ mit einem Ein-/Aus-Schalter für jeden Detektor und jede Drittanbieter-Blockliste; ein Panel „Firewall-Skript“ (wie viele Regeln ein Rendern schreiben würde, ob das Skript auf der Festplatte veraltet ist und aus welchen Sites und Bot-Listen es gerendert wird); ein Panel „Geplant“, das die Jobs des internen Cron und deren letzten Ausführungszeitpunkt anzeigt (mit einem Spinner neben jedem Job, der gerade im Hintergrund läuft); und ein Log dessen, was die App zuletzt getan hat. Ein Statusstreifen unter den Tabs zeigt die Gesundheitsprüfungen des Hosts auf jedem Bildschirm. Up/Down wechseln zwischen den drei Listen; m schaltet den Geo-Modus um. Drücke F, um die aktuellen Firewall-Regeln in ein Skript zu rendern — das Popup hat außerdem einen Schalter „nach dem Schreiben anwenden“ (Leertaste), um es tatsächlich sofort durchzusetzen, statt es danach von Hand anzuwenden. Drei weitere Tasten wirken auf den gesamten Host: u lädt jede Liste herunter, a wendet beide Ebenen an (NGINX, dann die Firewall), und w stellt diese Konsole hinter NGINX — dieselben drei, die der Browser als Buttons und ein Panel hat.
  • Bot-Einstellungen: listet jede bekannte Bot-Listen-Quelle auf (mit einer Aktion zum Aktualisieren) und jeden einzelnen Bot, durchsuchbar nach Namen, mit einer Überschreibung pro Bot (Erlaubt / Blockiert / dem Kategorie-Standardwert folgen).
  • Site-Einstellungen: ein Panel „NGINX-Einstellungen“ (Tab zum Fokussieren), das die hostweiten Auswahlmöglichkeiten enthält, die die generierte Konfiguration prägen — was eine blockierte Anfrage zurückbekommt (siehe unten), ob eine generierte robots.txt ausgeliefert werden soll und Rate Limiting — über jeder auf der Festplatte entdeckten NGINX-Site, jede mit einem Live-Status „aktuell / veraltet / nicht gefunden“ und Aktionen, um die aktuelle Richtlinie auf eine Site oder alle anzuwenden. Das Ändern einer dieser Einstellungen setzt jede angewendete Site auf STALE, was dein Signal zum erneuten Anwenden ist. Das Öffnen einer Site lässt dich ihre Kategorie-/Bot-Richtlinie überschreiben, eine der sechs Request-Shape-Regeln einschalten und Pfade auflisten, die vom Blockieren ausgenommen sind.
  • Dynamischer Schutz: eine Live-, handlungsfähige Ansicht dessen, was gerade auf den Server trifft — „Top IPs, die eine SSH-Verbindung versuchen“ und „Top User Agents“, jeweils nach Anzahl sortiert und markiert NOT BLOCKED/BLOCKED (rot dargestellt). Tab/Shift+Tab wechseln, auf welches der beiden Panels Up/Down wirken; f durchläuft einen gemeinsamen Filter (alle / nur nicht blockierte / nur blockierte); Enter blockiert die ausgewählte NOT BLOCKED-Zeile oder hebt die Blockierung auf, wenn sie bereits BLOCKED ist. i untersucht die ausgewählte Adresse: welche der Reputations-Feeds sie auflisten, ob sie innerhalb eines veröffentlichten Crawler-Bereichs liegt (was einen echten Googlebot von einem User Agent unterscheidet, der es nur behauptet), zu welchem Land sie gehört und als welche Konten sie sich anzumelden versuchte. Alles aus Listen, die dieser Host bereits heruntergeladen hat — es gibt hier kein Reverse- DNS oder Whois-Lookup, weil ein PTR-Eintrag von demjenigen geschrieben wird, dem die Adresse gehört, und angreifergelieferter Text wäre, der als autoritativ gelesen wird.
  • Hilfe: die vollständige Tastenbelegungsreferenz.

Bot-Einstellungen, wo jede Listen-Quelle und jeder einzelne Bot lebt:

Bot-Einstellungen: die drei Bot-Listen-Quellen mit ihren Anzahlen und eine Suche, die fünf Bots über Kategorien hinweg findet

Site-Einstellungen, wo die hostweiten NGINX-Auswahlmöglichkeiten über jeder auf der Festplatte gefundenen Site stehen:

Site-Einstellungen: Block-Antwort, robots.txt und Rate Limiting über zwei Sites, markiert mit UP TO DATE und STALE

Dynamischer Schutz, die Live-Ansicht dessen, was gerade jetzt auf den Server trifft:

Dynamischer Schutz: fehlgeschlagene SSH-Logins und Top User Agents, jede Zeile markiert mit BLOCKED, BLOCKLIST oder NOT BLOCKED

Wogegen es tatsächlich schützt

Verwendung der NGINX-Konfiguration

  • Bekannte Bots, nach Kategorie (Scanner / Suchmaschine / KI-Crawler), bezogen aus ArcJet's Well-Known Bots, ai.robots.txt und der NGINX Ultimate Bad Bot Blocker Liste. Das Blockieren einer Kategorie fügt eine if ($http_user_agent ...)-Regel in die NGINX- Konfiguration jeder Site ein (apply-blocks / a/A in den Site-Einstellungen).

  • Zu viele Anfragen, über NGINXs eigenes Rate Limiting. Anders als alles andere hier wird dies von NGINX zur Anfragezeit durchgesetzt, statt einen Log danach zu analysieren. Standardmäßig aus: ein für die falsche Site abgestimmtes Limit weist echte Besucher ab.

  • Zuerst höflich — eine optionale generierte robots.txt, die jeden Bot auflistet, den du blockierst, für die Crawler, die sie respektieren, plus den Honeypot-Pfad unten. Standardmäßig aus, weil sie ersetzt, was deine Site heute unter /robots.txt ausliefert.

  • Außer wo du etwas anderes sagst — Pfad-Ausnahmen pro Site, sodass du KI-Crawler überall außer /blog blockieren kannst.

  • Anfragen, die nicht wie ein Browser aussehen, pro Site. Sechs unabhängige Regeln, jede mit eigenem Schalter und jede standardmäßig aus — ein Schalter pro Regel, damit du, wenn etwas von dir aufhört zu funktionieren, erkennen kannst, welche Regel es verursacht hat:

    Zwei Schutzmaßnahmen gelten für alle und werden durchgesetzt, statt dir überlassen zu werden:

    • Die beiden TLS-abhängigen Regeln werden nur in HTTPS-server-Blöcke geschrieben. Browser machen kein HTTP/2 ohne TLS, also ist auf einem einfachen listen 80-Block jede Anfrage HTTP/1.1 — einschließlich der Weiterleitung, die ein Browser auf dem Weg zu HTTPS macht. Deine Port-80- und Port-443- Blöcke teilen sich üblicherweise einen server_name, sodass die Einstellung beide erreicht; nur der TLS-Block bekommt diese Regeln. Die Header-Shape-Regeln funktionieren über einfaches HTTP und werden in beide geschrieben.
    • /.well-known/ ist immer ausgenommen, sobald eine Regel aktiv ist. Dort holt Let's Encrypt seine HTTP-01-Challenge, über HTTP/1.1 ohne Accept und oft ohne User-Agent — ohne die Ausnahme hört dein Zertifikat Wochen später auf, sich zu erneuern.

Was eine blockierte Anfrage tatsächlich bekommt

Eine hostweite Auswahl, in den Site-Einstellungen. Diese Statuscodes sind nicht austauschbar — jeder sagt etwas anderes, und der Unterschied zählt am meisten für die Clients, die du nicht treffen wolltest:

OptionWofür sie gedacht ist
403 Forbidden (Standard)sagt, dass die Blockierung absichtlich war; die einzige, auf die ein fälschlich getroffener Mensch reagieren kann
404 Not Foundverbirgt, dass überhaupt etwas blockiert wurde
410 Gonebittet wohlerzogene Crawler, die URL endgültig zu verwerfen — bevorzuge dies gegenüber 403, wenn du Crawler statt Angreifer abweist
429 Too Many Requestssagt einem höflichen Client, sich zurückzuziehen und es erneut zu versuchen
418 I'm a teapotder Scherz aus RFC 2324. Er funktioniert; er ist nur nicht IANA-registriert, und NGINX sendet ihn mit leerem Body
444 close connectionüberhaupt keine Antwort; am günstigsten, aber nicht von einem ausgefallenen Server zu unterscheiden
Tarpitantwortet mit 403, tröpfelt aber den Body mit einem Byte pro Sekunde, sodass der Client wartet, statt weiterzuziehen

Der Tarpit ist die sanfteste Option bei einem Fehlalarm — ein fälschlich getroffener Client wird verlangsamt, nicht abgewiesen — und die härteste bei den Kosten für einen Bot, dessen Verbindung untätig bleibt. Zwei Dinge, die du vor der Wahl wissen solltest: Er hält auch für die Dauer eine deiner Worker-Verbindungen, sodass eine Flut getarpiteter Clients mit echten Besuchern um worker_connections konkurriert; und wie lange er tatsächlich dauert, hängt davon ab, wie NGINX einen kleinen Fehler-Body zu schreiben wählt, was in TODO.md als gegen einen echten Server zu prüfen vermerkt ist.

Aus deinen Logs, automatisch

Jede davon ist ein unabhängiger Schalter im Panel „Automatisches Blockieren“ des Dashboards, und jede fügt eine temporäre Firewall-Blockierung hinzu, die von selbst abläuft und erneut hinzugefügt wird, wenn das Verhalten anhält.

Sie laufen auf einem internen Timer, der deine SSH- und NGINX-Zugriffslogs jede Minute neu liest — aber nur, solange die TUI oder die Web-UI läuft. Beide halten denselben Zeitplan, in derselben Datenbank, sodass es reicht, die Web-UI laufen zu lassen; nichts wird erkannt, wenn keine von beiden läuft. Für einen Server ganz ohne stop-bots-Prozess siehe Unbeaufsichtigt, per Cron unten.

  • SSH- und Web-Scanner: IPs mit einer Menge fehlgeschlagener SSH-Logins oder vielen verschiedenen 404-Pfaden. Niemals eine IP mit einem kürzlichen erfolgreichen SSH-Login oder eine innerhalb des veröffentlichten IP-Bereichs eines bekannten Crawlers.
  • Gefälschte Crawler: alles, was sich als Googlebot, Bingbot oder GPTBot aus einer Adresse ausgibt, die der Betreiber dieses Crawlers selbst nicht veröffentlicht. Die billigste gängige Tarnung überhaupt, und die veröffentlichten CIDR-Listen entscheiden es. Inert, bis diese Listen tatsächlich abgerufen wurden.
  • Sondieren nach exponierten Geheimnissen: eine einzelne Anfrage nach /.env, /.git/config, /wp-config.php und Ähnlichem ist für sich genommen schlüssig, also braucht dies keine Schwelle. Die eingebaute Liste lässt bewusst Pfade weg, die irgendwo legitim sind — /wp-login.php, /wp-admin/, /xmlrpc.php, /phpmyadmin — da das Aussperren deines eigenen Administrators schlimmer wäre als einen Scanner zu verpassen, den der 404-Detektor ohnehin fängt. Füge eigene mit set-probe-paths hinzu.
  • Honeypot: ein Pfad, der nur als Disallow: in der generierten robots.txt veröffentlicht und nirgends verlinkt ist. Ihn zu erreichen bedeutet, robots.txt zu ignorieren, was nichts Legitimes versehentlich tut — das stärkste Signal hier und die längste Blockierung. Erfordert, dass die robots.txt-Generierung eingeschaltet ist, um überhaupt zu funktionieren.

Drei weitere betrachten, wie ein Client sich verhält, statt wonach er fragt. Alle drei sind standardmäßig aus, weil jeder einen Fehlalarm hat, den er nicht allein ausschließen kann — und alle drei nehmen verifizierte Suchmaschinen-Crawler aus, die sonst auf jeden von ihnen passen würden:

  • Lädt keine Assets: viele verschiedene Seiten und kein einziges Stylesheet, Skript oder Bild. Browser laden, was zu einer Seite gehört. Fängt keinen API-Client (er zählt verschiedene Pfade, und ein API-Client trifft wenige) oder einen gut gecachten wiederkehrenden Besucher (ein 304 zählt als geladenes Asset). Kann dir auf einer Site nicht helfen, die überhaupt keine Assets ausliefert — eine reine JSON-API.
  • Rotierender User Agent: mehrere Identitäten aus einer Adresse. Erheblich abgeschwächt durch NAT: ein Carrier-, Campus- oder Büro-Gateway präsentiert viele echte Browser auf einer IP, und ohne Zeitstempel-Analyse gibt es keine Möglichkeit, das von einem Scraper zu unterscheiden, der Agents durchwechselt.
  • Crawlt ohne Referer: viele verschiedene tiefe Seiten, niemals ein Referer. Abgeschwächt durch Referrer-Policy: no-referrer und Datenschutz-Tools; die Schwelle für verschiedene Pfade ist das, was es überhaupt brauchbar macht.

Nach Adresse

  • Ganze Länder, über IPdenys aggregierte CIDR-Listen — blockiere bestimmte Länder oder wechsle in den Allow-List-Modus und blockiere alles andere.
  • Bekannt bösartige Adressen, über Drittanbieter-Listen: FireHOL Level 1, Tor-Exit-Nodes und blocklist.de. Alle standardmäßig aus.
  • Ganze Hosting-Anbieter: AWS, Google Cloud und DigitalOcean veröffentlichen ihren Adressraum, und private Besucher browsen nicht von dort. Diese sind grobe Instrumente und als solche gekennzeichnet — sie blockieren jeden dort gehosteten Besucher, einschließlich VPN-Endpunkten, Unternehmens-Egress und API-Clients, nicht nur Bots. Standardmäßig aus, mit einer Warnung, wenn du einen einschaltest.
  • Benachbarte Adressen, optional: wenn mehrere Adressen in einem IPv4-/24 im selben Durchlauf markiert werden, blockiere das /24. Standardmäßig aus — 256 Adressen zu blockieren, weil drei sich schlecht benommen haben, ist Kollateralschaden by design. (IPv6 ist anders und braucht keinen Schalter: Eine Erkennung blockiert immer das /64, weil ein /64 ein LAN ist, dasselbe, was eine einzelne IPv4-Adresse repräsentiert. Die einzelne Adresse zu blockieren, die ein IPv6-Angreifer zufällig benutzt hat, würde nichts stoppen — er hat 2^64 weitere.)
  • Alles andere, von Hand — füge direkt eine IP/CIDR-Allow- oder -Block-Regel hinzu oder nutze den Dynamic- Protection-Bildschirm, um eine bestimmte IP oder einen User Agent dauerhaft zu blockieren, die du entdeckt hast, bevor sie jemals eine automatische Schwelle überschreitet.

Funktioniert es tatsächlich?

Alles oben ist generiert. Ob irgendetwas davon in Kraft ist, ist eine separate Frage, und stop-bots status ist diejenige, die sie beantwortet:``` stop-bots status

root@kitploit:~
Sieben Prüfungen, und die erste ist die, die es wert ist: Sind die generierten Regeln tatsächlich im Kernel oder nur auf der Festplatte? Ein echter Host lief drei Wochen lang mit 48.860 Drop-Regeln in `/etc/stop-bots/firewall.nft` und einem leeren Ruleset, weil das Schreiben des Skripts und das Laden zwei Schritte sind und niemand jemals den zweiten betrachtet hatte.

Der Rest: Übersteht das Ruleset einen Neustart (`nftables.service` aktiviert?), stimmt das Skript noch mit den Regeln überein, sind die NGINX-Blöcke angewendet, läuft der Konsolendienst mit der Binärdatei, die er angibt, ist Platz für die Datenbank vorhanden, und können die Detektoren ihre Logs lesen.

Es beendet sich mit einem Nicht-Null-Code, wenn etwas **CRITICAL** ist, sodass es als Monitoring-Check funktioniert. `--quiet` gibt nur aus, was Aufmerksamkeit erfordert, was die Form für cron ist:```
0 * * * * /usr/local/bin/stop-bots status --quiet

Eine Prüfung, die nicht ausgeführt werden konnte — nft list benötigt Root-Rechte — meldet UNKNOWN, niemals OK. Eine Zustandsprüfung, die meldet, dass alles in Ordnung sei, weil sie nicht nachsehen konnte, ist schlimmer als keine, denn ihr wird geglaubt.

Derselbe Bericht befindet sich im Dashboard sowohl in der Konsole als auch in der TUI, stündlich vom internen Cron erstellt statt bei jedem Rendern: nft list auf einem großen Regelwerk sind Megabytes an Text.

Nichts geschieht ohne dich

Jede Firewall-Entscheidung oben wird generiert, niemals automatisch angewendet: render-firewall (oder die f-Taste des Dashboards) schreibt ein iptables- oder nftables-Skript, das du selbst prüfen und anwenden kannst, und weigert sich, eines zu schreiben, das eine aktuell verbundene SSH-Sitzung aussperren würde.

Drei Dinge können es für dich anwenden, und alle drei erfordern, dass du danach fragst: das Render-Popup der TUI („nach dem Schreiben anwenden") oder ihre a-Taste, das Firewall-Panel der Web-Konsole („nach dem Schreiben ausführen") oder ihre Schaltfläche „Alles anwenden", und batch --apply aus einem von dir geschriebenen Crontab — siehe Unbeaufsichtigt, aus cron. Nichts davon ist ein Nebeneffekt von irgendetwas Automatischem: Der interne Cron rendert das Skript und führt es niemals aus.

Dasselbe gilt auf der NGINX-Seite: Eine Einstellung zu ändern ändert nur, was geschrieben würde. Die Site-Einstellungen zeigen jede Site als STALE, bis du sie anwendest.

Einen Detektor abzuschalten entfernt niemals bereits hinzugefügte Sperren — diese laufen von selbst ab. „Erkennung stoppen" und „rückgängig machen, was erkannt wurde" sind bewusst getrennt; Letzteres ist der Bildschirm „Dynamic Protection" oder remove-firewall-rule.

Es gibt außerdem eine einfache Zugriffsprotokoll-Zählung, unabhängig vom Blockieren: record-access-stats / list-access-stats zählen, wie oft jeder User-Agent in erfolgreichen (fehlerfreien) Anfragen auftaucht, sodass du sehen kannst, wer tatsächlich zu Besuch ist, zusätzlich dazu, wer blockiert wird.

Unbeaufsichtigt, aus cron

stop-bots batch ist ein Durchlauf über alles, was die TUI von Hand tut: jede Liste aktualisieren, die Logs scannen, die NGINX-Blockierungsregeln und das Firewall-Skript schreiben.```

One full pass a night. Refreshes the lists, scans the logs, applies both.

0 4 * * * root /usr/local/bin/stop-bots batch --apply --ssh-log /var/log/auth.log

And detection every ten minutes, without re-downloading lists that change weekly.

*/10 * * * * root /usr/local/bin/stop-bots batch --apply --no-fetch --ssh-log /var/log/auth.log

root@kitploit:~
Es sagt nichts, wenn alles funktioniert hat, also schickt ein gesunder nächtlicher Lauf keine E-Mail. Ein fehlgeschlagener Schritt gibt eine Meldung auf stderr aus und setzt einen Exit-Status ungleich null, was dazu führt, dass cron Sie darüber informiert. Führen Sie es zuerst einmal manuell mit `--verbose` aus — das gibt eine Zeile pro Schritt aus und ist der einfachste Weg zu sehen, was es tatsächlich tut.

**`--apply` ist das, was es überhaupt etwas durchsetzen lässt.** Ohne es schreibt `batch` die NGINX-Konfiguration und das Firewall-Skript und hört dann auf: Die Konfiguration bewirkt nichts bis zu einem Reload, ein Skript bewirkt nichts, bis es ausgeführt wird. Das ist überall in diesem Projekt die Standardeinstellung, und hier bleibt es die Standardeinstellung.

`batch` und ein langlaufendes Front-End koexistieren sicher. Die TUI, die Web-UI und `batch` zeichnen alle auf, was sie getan haben, über dieselben Schlüssel in derselben Datenbank, sodass derjenige, der zuerst an einen Job gelangt, ihn erledigt und die anderen feststellen, dass er nicht mehr fällig ist — Sie bekommen keine zwei Erkennungsdurchläufe, und das Panel „Scheduled tasks" des Dashboards zeigt, was tatsächlich passiert ist, anstatt zu behaupten, alles sei überfällig. Wenn Sie die Web-UI bereits laufen lassen, ist der nächtliche `batch`-Eintrag eher eine Absicherung als eine Notwendigkeit; wenn nicht, ist er das Einzige, was die Erkennung aktuell hält.

**Mit `--apply` kann die SSH-Lockout-Schutzvorrichtung ablehnen — und eine Ablehnung bedeutet, dass nichts angewendet wird.** Sie lehnt ab, wenn die Regeln einen Client blockieren würden, der gerade jetzt verbunden ist, *und* wenn überhaupt kein SSH-Log gelesen werden konnte, weil dann die Prüfung nicht ausgeführt werden konnte. Das interaktive `render-firewall` gibt im zweiten Fall nur einen Hinweis aus, mit der Begründung, dass ein Mensch das Terminal beobachtet; von cron aus tut das niemand. **Übergeben Sie `--ssh-log` explizit**: cron läuft als root, sodass `/var/log/auth.log` normalerweise problemlos gelesen wird, aber auf einem reinen journald-Host kann `journalctl` unter cron leer zurückkommen, was genau der Fall ist, in dem abgelehnt wird. `--force` übergeht die Schutzvorrichtung, wenn Sie es ernst meinen.

Ein fehlgeschlagener Schritt stoppt nie die anderen, und die NGINX- und Firewall-Hälften sind unabhängig — ein fehlgeschlagener NGINX-Reload hinterlässt die Firewall trotzdem angewendet, und umgekehrt.

`batch` zeichnet jeden Schritt gegen denselben Zeitplan auf, den der interne cron der TUI verwendet, sodass beide darin übereinstimmen, was bereits gelaufen ist, anstatt es beide zu tun, und das Panel „Scheduled tasks" des Dashboards zeigt, was Ihr echter cron getan hat.

# Die Web-UI

`stop-bots web` liefert dieselben fünf Bildschirme in einem Browser aus.```
stop-bots web

Es bindet 127.0.0.1:8787 — nur von dieser Maschine aus erreichbar — und gibt beim ersten Start einmalig ein generiertes Passwort aus. Erreiche es von deinem Laptop aus über einen SSH-Tunnel:``` ssh -L 8787:127.0.0.1:8787 your-server

root@kitploit:~
then open <http://127.0.0.1:8787/>.

![The web console's dashboard: health chips and the two host-wide buttons in the header, policy, geo-blocking and third-party feeds in one column, automatic blocking and scheduled tasks in the other](https://assets.kitploit.com/production/public/readmes/55148/73bbcc92f0f3d2c9d0586bd71ad18f1b4d582fa59824b4f5e3c97e08575f5070/bb45db648f6a59192f56b1e14a019f50f0816bff651766316c377cbe79f700b6-display-v1.webp)

The console follows the operating system's light or dark setting, with a toggle in the
header; the TUI screenshots above are the dark theme, these the light one. The keys the
TUI uses work here too: `1`–`4` switch screens, `/` focuses the search box, `?` opens Help.

![The web console's Dynamic Protection page: failed SSH logins and top user agents, each with a count bar and a state tag, and a block or unblock button per row](https://assets.kitploit.com/production/public/readmes/55148/090d4d2151eb00a69781c44351abe10f268d8031816199b9aeb5b4d2cddfc5f5/52a05387d1227288e7f45ece3c33e4af17957d8e9e73fb7c0213d64c49dc7419-display-v1.webp)

Three host-wide actions live in the header, in the browser as buttons and in the TUI
as single keys:

- **Update everything** (`u`) downloads every bot list, every crawler IP range, every
  *enabled* reputation feed and every *selected* country — the same set `stop-bots batch`
  fetches, from the same plan. One source failing does not stop the rest, and nothing is
  enforced until something applies it.
- **Apply everything** (`a`) writes and reloads the NGINX config, then writes and runs the
  firewall script. The two planes are independent: whichever fails, the other still gets
  its turn, because a half-applied host beats one where an NGINX syntax error also left
  the firewall stale.
- **Web Access** (`w`) sets NGINX up to serve the console itself — see
  [Behind NGINX](#behind-nginx-a-subdomain-or-a-path-prefix).

## As a service (Debian)```
sudo stop-bots install web

Schreibt /etc/systemd/system/stop-bots-web.service, erstellt /var/lib/stop-bots (0700 — es enthält den Passwort-Hash der Konsole) und /etc/stop-bots, generiert ein Passwort, falls noch keines existiert, und aktiviert und startet die Unit.

--dry-run gibt den gesamten Plan aus und ändert nichts. Dies ist der einzige Befehl im Projekt, der einen Daemon startet, also fange dort an. --prefix <dir> schreibt denselben Baum an einen Ort, den du ohne Root lesen kannst. Wenn die Unit bereits existiert und du sie bearbeitet hast, stoppt der Installer und teilt dies mit, anstatt deine Änderung zu überschreiben; --force, wenn du es ernst meinst.

Der Dienst läuft als root, weil die Konsole /etc/nginx umschreibt, das Firewall-Skript schreibt und nginx -t sowie systemctl reload nginx ausführt. Es gibt keine unprivilegierte Aufteilung, die den Funktionsumfang intakt lässt. Die Unit trägt die Härtung, die diese Anforderung übersteht, sowie einen Kommentar, der angibt, welche Härtung weggelassen wurde und warum.

Die Bind-Adresse, die Host-Allowlist und das Pfad-Präfix sind bewusst nicht in der Unit — der laufende Server liest sie erneut aus der Datenbank, sodass sie in ExecStart zwei Quellen der Wahrheit hätten. Ändere sie mit stop-bots web --save ... und starte neu.

Eine Sache ändert sich, sobald dies als root läuft: Der tägliche RenderFirewall-Job des internen Cron kann nun /etc/stop-bots/firewall.nft schreiben, was nicht möglich war, als du die Konsole manuell als du selbst ausgeführt hast. Nichts wendet dieses Skript an — es auszuführen bleibt weiterhin dir überlassen.

Es wird nur auf Debian geprüft, weil das getestet wurde; die Unit ist sehr wahrscheinlich auf jeder systemd-Distribution korrekt, aber der angenommene SSH-Log-Pfad ist der von Debian.

Exponieren

Etwas anderes als Loopback zu binden, erfordert ein zweites, bewusstes Flag, weil diese Konsole die Firewall und die NGINX-Konfiguration des Hosts, auf dem sie läuft, umschreiben kann:``` stop-bots web --bind 0.0.0.0:8787 --expose --allowed-hosts admin.example.com --save

root@kitploit:~
`--allowed-hosts` ist in der Praxis nicht optional: Eine Anfrage mit einem Hostnamen, der nicht
aufgeführt ist, wird abgelehnt. Das ist es, was DNS-Rebinding gegen die Konsole scheitern lässt, und es ist
der Grund, warum ein exponierter Server, der über einen Namen erreicht wird, den Namen explizit benötigt.

Setzen Sie ihn hinter NGINX mit TLS — denselben NGINX, den dieses Tool schützt. Wenn Sie das tun und der
Proxy `X-Forwarded-For` setzt, teilen Sie der Konsole mit, dass sie diesem Header vertrauen darf, sonst kann sie nicht
erkennen, von welcher Adresse eine Anfrage wirklich kam:```
stop-bots web --bind 127.0.0.1:8787   # and set web:trust_forwarded_for

Hinter TLS setzen Sie außerdem web:secure_cookie. Ohne dies sendet ein Browser das Session- Cookie auch an eine http://-URL für denselben Host.

web:trust_forwarded_for ist wichtiger, als es aussieht. Ohne dies kommt jede Anfrage hinter einem Proxy von 127.0.0.1 an, sodass die Konsole einen Client nicht von einem anderen unterscheiden kann — was bedeutet, dass eine Flut von Login-Versuchen denselben Throttle-Bucket wie Sie teilt und der Guard, der Sie daran hindert, Ihre eigene Adresse zu blockieren, nichts zum Vergleichen hat. Mit dieser Option funktionieren beide pro Client.

Hinter NGINX: eine Subdomain oder ein Pfadpräfix

Die Konsole kann dies für Sie einrichten, und die TUI kann das auch (w auf dem Dashboard). Beide schreiben die NGINX-Konfiguration, zeichnen das Pfadpräfix auf und fügen den Hostnamen zur Allowlist hinzu — die drei Dinge, die übereinstimmen müssen, denn ein fehlendes Präfix lässt jeden Link den location-Block verlassen und ein fehlender Hostname macht jede Anfrage zu einem 403. Beide validieren mit nginx -t, bevor die Konfiguration wirksam werden kann, machen sie rückgängig, wenn dies fehlschlägt, und zeichnen die neue Adresse erst auf, nachdem sie validiert wurde.

Zwei Modi, und Pfad ist aus einem Grund die Standardeinstellung: Er fügt einen location-Block zu einer Site hinzu, die Sie bereits haben, sodass die Konsole das Zertifikat dieser Site erbt. Eine Subdomain benötigt ein eigenes, und bis certbot --nginx -d <host> ausgeführt wurde, übertragen das Passwortformular und das Session- Cookie dieser Konsole Daten unverschlüsselt über das Netzwerk.

Der Rest dieses Abschnitts behandelt dasselbe manuell, was es wert ist, einmal gelesen zu werden, selbst wenn Sie das Panel verwenden — die unten beschriebene Trailing-Slash-Falle ist der Fehler, den es zu verhindern gilt.

Eine Subdomain ist die einfachere Bereitstellung, und die, die Sie wählen sollten, wenn Sie können:```nginx server { server_name stopbots.example.com; location / { proxy_pass http://127.0.0.1:8787; proxy_set_header Host $host; } }

root@kitploit:~
| `-s` | `--server` | Server URL (default: `http://localhost:8080`) |
| `-t` | `--token` | API token for authentication |
| `-o` | `--output` | Output format: `json`, `yaml`, `table` (default: `table`) |
| `-v` | `--verbose` | Enable verbose output |
| `-q` | `--quiet` | Suppress non-essential output |
| `-h` | `--help` | Show help message |
| `-V` | `--version` | Show version information |

### Beispiele

```bash
# Standardverbindung zum lokalen Server
kitploit-cli scan --target example.com

# Verbindung zu einem Remote-Server mit Authentifizierung
kitploit-cli scan --target example.com --server https://api.example.com --token YOUR_TOKEN

# Ausgabe im JSON-Format
kitploit-cli scan --target example.com --output json

# Ausführliche Ausgabe aktivieren
kitploit-cli scan --target example.com --verbose

Konfigurationsdatei

Die CLI unterstützt eine Konfigurationsdatei unter ~/.kitploit/config.yaml:

root@kitploit:~
server: http://localhost:8080
token: your-api-token
output: table
verbose: false
timeout: 30

Umgebungsvariablen

VariableBeschreibung
KITPLOIT_SERVERServer-URL
KITPLOIT_TOKENAPI-Token
KITPLOIT_OUTPUTAusgabeformat
KITPLOIT_TIMEOUTTimeout in Sekunden

Verwendung der API

Authentifizierung

Alle API-Anfragen erfordern einen gültigen API-Token im Authorization-Header:

root@kitploit:~
Authorization: Bearer YOUR_API_TOKEN

Endpunkte

MethodeEndpunktBeschreibung
GET/api/v1/healthIntegritätsprüfung
GET/api/v1/scansAlle Scans auflisten
POST/api/v1/scansNeuen Scan starten
GET/api/v1/scans/{id}Scan-Details abrufen
DELETE/api/v1/scans/{id}Scan löschen
GET/api/v1/scans/{id}/resultsScan-Ergebnisse abrufen

Beispielanfragen

root@kitploit:~
# Integritätsprüfung
curl http://localhost:8080/api/v1/health

# Neuen Scan starten
curl -X POST http://localhost:8080/api/v1/scans \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"target": "example.com", "scan_type": "full"}'

# Scan-Ergebnisse abrufen
curl http://localhost:8080/api/v1/scans/SCAN_ID/results \
  -H "Authorization: Bearer YOUR_API_TOKEN"

Fehlerbehebung

Verbindung zum Server nicht möglich

  1. Stellen Sie sicher, dass der Server läuft:

    root@kitploit:~
    curl http://localhost:8080/api/v1/health
    
  2. Überprüfen Sie die Firewall-Einstellungen und stellen Sie sicher, dass der Port nicht blockiert ist.

  3. Überprüfen Sie die Server-URL in Ihrer Konfigurationsdatei oder den Umgebungsvariablen.

Authentifizierungsfehler

  1. Überprüfen Sie, ob Ihr API-Token gültig und nicht abgelaufen ist.

  2. Stellen Sie sicher, dass der Authorization-Header korrekt formatiert ist.

  3. Überprüfen Sie, ob Ihr Konto über die erforderlichen Berechtigungen verfügt.

Scan schlägt fehl oder bleibt hängen

  1. Überprüfen Sie die Serverprotokolle auf Fehlermeldungen:

    root@kitploit:~
    docker logs kitploit-server
    
  2. Erhöhen Sie den Timeout-Wert in Ihrer Konfiguration.

  3. Stellen Sie sicher, dass das Ziel erreichbar ist und nicht durch eine Firewall blockiert wird.

Hohe Speicherauslastung

  1. Reduzieren Sie die Anzahl gleichzeitiger Scans.

  2. Erhöhen Sie die Speichergrenzen in Ihrer Docker-Konfiguration.

  3. Überprüfen Sie die Datenbankgröße und bereinigen Sie alte Scan-Ergebnisse.``` stop-bots web --allowed-hosts stopbots.example.com --save

root@kitploit:~
**Ein Pfadpräfix funktioniert ebenfalls**, aber die Konsole muss darüber informiert werden — sie muss jeden Link, jede Formularaktion, jede Weiterleitung und jeden Cookie-Pfad mit dem bereits enthaltenen Präfix generieren, und sie kann es nicht erraten:```
stop-bots web --base-path /stop-bots --allowed-hosts example.com --save

| -s | --server | Server-Modus aktivieren (erfordert --port) | | -p | --port | Port für den Server-Modus (Standard: 8080) | | -c | --config | Pfad zur Konfigurationsdatei | | -v | --verbose | Ausführliche Ausgabe aktivieren | | -h | --help | Hilfemeldung anzeigen | | -V | --version | Versionsinformationen anzeigen |

Beispiele

root@kitploit:~
# Grundlegende Verwendung
python main.py

# Server-Modus auf Port 9000
python main.py --server --port 9000

# Mit benutzerdefinierter Konfiguration
python main.py --config /path/to/config.yaml

# Ausführlicher Modus
python main.py --verbose

Konfiguration

Die Anwendung kann über eine YAML-Konfigurationsdatei konfiguriert werden:

root@kitploit:~
server:
  host: "0.0.0.0"
  port: 8080
  debug: false

database:
  url: "postgresql://localhost:5432/mydb"
  pool_size: 10

logging:
  level: "INFO"
  format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"

Entwicklung

Projektstruktur

root@kitploit:~
project/
├── src/
│   ├── __init__.py
│   ├── main.py
│   ├── config.py
│   └── utils/
│       ├── __init__.py
│       └── helpers.py
├── tests/
│   ├── __init__.py
│   └── test_main.py
├── requirements.txt
└── README.md

Tests ausführen

root@kitploit:~
# Alle Tests ausführen
pytest

# Mit Coverage
pytest --cov=src

# Bestimmte Testdatei ausführen
pytest tests/test_main.py

Beitragen

  1. Repository forken
  2. Feature-Branch erstellen (git checkout -b feature/amazing-feature)
  3. Änderungen committen (git commit -m 'Add amazing feature')
  4. Branch pushen (git push origin feature/amazing-feature)
  5. Pull Request öffnen

Lizenz

Dieses Projekt ist unter der MIT-Lizenz lizenziert – siehe die Datei LICENSE für Details.

Danksagungen

  • Besonderer Dank an alle Mitwirkenden
  • Inspiration durch ähnliche Open-Source-Projekte
  • Community-Feedback und Unterstützung```nginx location /stop-bots/ { proxy_pass http://127.0.0.1:8787; # NO trailing slash proxy_set_header Host $host; }
root@kitploit:~
**Der abschließende Schrägstrich bei `proxy_pass` ist entscheidend, und sein Fehlen ist der ganze Trick.**
Ohne ihn leitet NGINX den vollständigen Pfad weiter, und `stop-bots` sieht
`/stop-bots/whatever`, was es nun ausliefert und generiert. *Mit* einem abschließenden
Schrägstrich entfernt NGINX das Präfix — und dann löst der Browser die Links auf der Seite
gegen die Domain-Wurzel auf, landet außerhalb des `location`-Blocks, und alles gibt 404 zurück. Keine
noch so große Sorgfalt auf der Serverseite kann das beheben, also muss das Präfix den
Proxy überleben.

Von außen erzwingt das nichts, aber der Fehler ist laut statt subtil: mit dem
konfigurierten Präfix ist eine Anfrage ohne Präfix ein einfacher 404 statt einer Seite, die
halb funktioniert.

## Was es nicht tun wird

Zwei Dinge fehlen absichtlich, und der Hilfe-Bildschirm sagt das mit den Gründen:

- **Es wird nichts entsperren, was eine heruntergeladene Liste blockiert hat** — die nächste Aktualisierung dieser
  Liste würde es stillschweigend rückgängig machen.
- **Es wird sein eigenes Passwort nicht ändern.** Verwenden Sie `stop-bots web --set-password` auf dem Host.

Es weigert sich außerdem, die Adresse zu blockieren, von der Sie verbunden sind, was die
Konsole entfernen würde, mit der Sie es rückgängig machen würden.

**Früher waren es drei.** Das Anwenden des Firewall-Skripts war das dritte, mit der Begründung, dass
seine Ausführung die einzige Operation ist, die den Host vom Netzwerk trennen kann. Das ist jetzt
verfügbar — „Apply everything" auf dem Dashboard (`a` in der TUI), oder das Kästchen „run it after
writing" im Firewall-Panel — weil die Absicherung, die es von cron aus sicher macht, es auch von einem
Knopf aus sicher macht: Die Regeln werden gegen die aktuell über SSH angemeldeten Clients geprüft, in der
Reihenfolge, in der das Skript selbst sie auswerten wird, und eine Regel, die einen von ihnen blockieren würde, ist eine
Ablehnung statt einer Warnung. Starten Sie die Konsole mit `--no-apply`, um das alte
Nur-Schreib-Verhalten zurückzubekommen.

Anmeldeversuche werden gedrosselt. Nicht weil das Passwort erratbar wäre — es wird generiert,
144 Bit — sondern weil die Verifizierung eines Versuchs Argon2id ausführt, und einen nicht authentifizierten Aufrufer
das so schnell betreiben zu lassen, wie er posten kann, ein Denial of Service gegen den Host ist, den dieses Tool
schützen soll. Zehn falsche Versuche sind kostenlos; danach zieht sich ein Client exponentiell
zurück, und eine globale Obergrenze begrenzt die CPU unabhängig davon, von wie vielen Adressen die
Versuche kommen.

## NGINX in einem Container ausführen

Wenn NGINX in Docker läuft und seine Konfiguration auf einem Bind-Mount liegt, lädt `systemctl reload nginx` nichts
neu. Richten Sie die beiden Befehle stattdessen auf den Container — das gilt auch für die CLI und die
TUI:```
stop-bots set-nginx-commands \
  --test   "docker exec web nginx -t" \
  --reload "docker exec web nginx -s reload"

Der Befehl wird in Wörter aufgeteilt und direkt ausgeführt. Er durchläuft niemals eine Shell, daher sind ;, | und $VAR gewöhnliche Zeichen und keine Syntax.

Mitwirken

Wie der Code aufgebaut ist, wie er getestet wird und nach welchen Regeln er geschrieben wird, steht in CONTRIBUTING.md. Der Release-Prozess steht in RELEASING.md.

Kontakt

Du kannst mich unter [email protected] erreichen.

Lizenz

Copyright (C) 2026 Marko Ivankovic

Dieses Programm ist freie Software: Du kannst es unter den Bedingungen der GNU Affero General Public License, wie von der Free Software Foundation veröffentlicht, weitergeben und/oder modifizieren, entweder gemäß Version 3 der Lizenz oder (nach deiner Wahl) jeder späteren Version.

Siehe die Datei LICENSE für den vollständigen Text der Lizenz.

Du kannst AGPL-Software nicht verwenden?

Eine alternative Lizenzierung ist NICHT verfügbar.

Tool herunterladen
RegelWeist ab, außer Bots
HTTP/1.0 und HTTP/1.1Crawler und API-Clients, die kein HTTP/2 sprechen
Kein Accept-Headermanche API-Clients senden keinen
Kein Accept-LanguageDatenschutz-Tools entfernen ihn
Leerer/fehlender User-AgentSkripte und Gesundheitsprüfungen lassen ihn oft weg
Host ist eine bloße IPbricht das Erreichen der Site per IP
TLS 1.0 / 1.1nur sehr alte Clients