Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
stop-bots — Automatisez le blocage des mauvais bots qui accèdent à votre serveur | Kitploit
Outils/GitHubGitHub/ivankovic/stop-bots
Outils DéfensifsAudit de ConfigurationCollecte d'InformationsSécurité WebSécurité RéseauUtilitaires et FrameworksDétection d'IntrusionAnti-BotAnalyse de Journaux
GitHubivankovic/stop-bots

stop-bots

Automatisez le blocage des mauvais bots qui accèdent à votre serveur

12il y a 1 jourPas encore vérifié
Voir le dépôt

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

Stop Bots

CI crates.io Coverage MSRV License: AGPL v3+

Une TUI, une interface web et une CLI qui vous aident à configurer votre serveur pour bloquer les mauvais bots sans vous cacher derrière un CDN.

Il fonctionne aux côtés de NGINX et de votre pare-feu existant (iptables ou nftables), sur deux plans distincts :

  • Configuration NGINX. - Il classe les bots connus par catégorie (scanners, moteurs de recherche, crawlers IA) et les bloque ou les autorise en injectant une règle dans les configurations de vos sites. Il analyse le journal NGINX pour détecter dynamiquement les bots et les bloquer même si aucun ensemble de règles ne les suit encore.
  • Un script de pare-feu. - Bloquez des pays entiers, des plages d'IP de centres de données, des plages d'IP de bots connus ou toute adresse IP qui tente à plusieurs reprises de se connecter à votre serveur sans succès.

Le tableau de bord stop-bots : catégories de bots à l'échelle du système, géoblocage, détecteurs automatiques et le cron interne

L'application fait de son mieux pour ne pas vous verrouiller hors du serveur, mais vous l'utilisez à vos propres risques. Et notez qu'elle est sous licence AGPL, donc si vous l'utilisez à des fins commerciales, assurez-vous de respecter la lettre de la licence.

Installation

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

root@kitploit:~
Ou compiler depuis un checkout :```
cargo install --path .

Un binaire Linux x86_64 précompilé est disponible sur les releases GitHub.

Dépendances

Nécessite Rust 1.88 ou plus récent pour compiler. Linux uniquement en pratique : il appelle systemctl, nginx -t et nft/iptables, donc bien qu'il compile ailleurs, il n'y sera guère utile.

Utilisation

Lancez le binaire sans argument pour démarrer la TUI, stop-bots web pour les mêmes écrans dans un navigateur (voir L'interface web), ou consultez stop-bots --help pour la liste complète des sous-commandes CLI. La TUI et la CLI peuvent être utilisées ensemble. Configurez tout dans la TUI et utilisez ensuite la CLI dans un crontab pour maintenir les règles à jour.

Vous pouvez quitter l'application, ou revenir en arrière depuis un popup/sous-menu, avec 'q' ou Échap.

Thème

Vous pouvez basculer entre le thème sombre et clair avec 't'. L'application tentera de détecter automatiquement le thème, mais pour certaines combinaisons de terminal et de multiplexeur, les informations disponibles ne suffisent pas pour faire le bon choix.

Écrans

1–4 (ou d/b/s/p) sautent directement à un écran ; Gauche/Droite, ou leurs alias vim h/l, les parcourent un par un ; ? affiche à tout moment une référence complète des raccourcis clavier, et : ouvre une palette de commandes listant chaque action par son nom. Tab / Shift+Tab déplacent toujours entre les panneaux de l'écran courant, jamais entre les écrans.

Le Dashboard possède tout ce qui finit dans le script de pare-feu ; les paramètres de site possèdent tout ce qui finit dans la configuration NGINX. Cette séparation détermine où vit chaque paramètre donné.

  • Dashboard (l'écran par défaut) : les valeurs par défaut des catégories à l'échelle du système (Scanners / Search Bots / AI Bots — Autorisés ou Bloqués) ; le géo-blocage à l'échelle de l'hôte (bloquer ou autoriser une liste de pays spécifiques) ; un panneau « Automatic blocking » avec un interrupteur on/off pour chaque détecteur et chaque blocklist tierce ; un panneau « Firewall script » (combien de règles un rendu écrirait, si le script sur disque est obsolète, et les sites et listes de bots à partir desquels il est généré) ; un panneau « Scheduled » montrant les tâches du cron interne et leur dernière exécution (avec un spinner à côté de toute tâche en cours d'exécution en arrière-plan) ; et un journal de ce que l'application a fait en dernier. Une bande de statut sous les onglets affiche les vérifications de santé de l'hôte sur chaque écran. Up/Down circulent entre les trois listes ; m change le mode géo. Appuyez sur F pour générer les règles de pare-feu actuelles dans un script — le popup dispose aussi d'un interrupteur « apply after writing » (Espace) pour l'appliquer réellement immédiatement, au lieu de l'appliquer à la main ensuite. Trois autres touches agissent sur l'ensemble de l'hôte : u télécharge toutes les listes, a applique les deux plans (NGINX, puis le pare-feu), et w place cette console derrière NGINX — les trois mêmes que le navigateur propose sous forme de boutons et d'un panneau.
  • Bot settings : liste chaque source de liste de bots connue (avec une action pour la rafraîchir) et chaque bot individuel, recherchable par nom, avec une dérogation par bot (Autorisé / Bloqué / suivre la valeur par défaut de la catégorie).
  • Site settings : un panneau « NGINX settings » (Tab pour le cibler) contenant les choix à l'échelle de l'hôte qui façonnent la configuration générée — ce qu'une requête bloquée reçoit en retour (voir ci-dessous), s'il faut servir un robots.txt généré, et la limitation de débit — au-dessus de chaque site NGINX découvert sur disque, chacun avec un statut en direct « up to date / stale / not found » et des actions pour appliquer la politique courante à un site ou à tous. Modifier l'un de ces paramètres fait passer chaque site appliqué à STALE, ce qui est votre signal pour réappliquer. Ouvrir un site vous permet de remplacer sa politique de catégorie/bot, d'activer l'une des six règles de forme de requête, et de lister les chemins exemptés de blocage.
  • Dynamic Protection : une vue en direct et actionnable de ce qui frappe actuellement le serveur — « Top IPs attempting SSH connection » et « Top User Agents », chacun classé par nombre et étiqueté NOT BLOCKED/BLOCKED (affiché en rouge). Tab/Shift+Tab changent lequel des deux panneaux Up/Down affecte ; f fait défiler un filtre partagé (tous / non bloqués uniquement / bloqués uniquement) ; Enter bloque la ligne NOT BLOCKED sélectionnée, ou la débloque si elle est déjà BLOCKED. i inspecte l'adresse sélectionnée : lesquels des flux de réputation la listent, si elle se trouve dans une plage de crawler publiée (ce qui distingue un vrai Googlebot d'un user agent qui prétend simplement l'être), à quel pays elle appartient, et quels comptes elle a tenté de utiliser pour se connecter. Tout cela à partir de listes que cet hôte a déjà téléchargées — il n'y a pas de reverse DNS ni de recherche whois ici, car un enregistrement PTR est écrit par celui qui détient l'adresse et serait un texte fourni par l'attaquant qui se lit comme faisant autorité.
  • Help : la référence complète des raccourcis clavier.

Bot settings, où vivent chaque source de liste et chaque bot individuel :

Bot settings: the three bot-list sources with their counts, and a search matching five bots across categories

Site settings, où les choix NGINX à l'échelle de l'hôte se trouvent au-dessus de chaque site trouvé sur disque :

Site settings: block response, robots.txt and rate limiting, above two sites tagged UP TO DATE and STALE

Dynamic Protection, la vue en direct de ce qui frappe le serveur en ce moment :

Dynamic Protection: failed SSH logins and top user agents, each row tagged BLOCKED, BLOCKLIST or NOT BLOCKED

Ce contre quoi il protège réellement

En utilisant la configuration NGINX

  • Les bots connus, par catégorie (scanner / moteur de recherche / crawler IA), issus de ArcJet's Well-Known Bots, ai.robots.txt et de la liste NGINX Ultimate Bad Bot Blocker. Bloquer une catégorie injecte une règle if ($http_user_agent ...) dans la configuration NGINX de chaque site (apply-blocks / a/A de Site settings).

  • Trop de requêtes, via la limitation de débit propre à NGINX. Contrairement à tout le reste ici, cela est appliqué par NGINX au moment de la requête plutôt qu'en analysant un journal après coup. Désactivé par défaut : une limite réglée pour le mauvais site éloigne de vrais visiteurs.

  • Poli, d'abord — un robots.txt généré en option listant chaque bot que vous bloquez, pour les crawlers qui le respectent, plus le chemin honeypot ci-dessous. Désactivé par défaut, car il remplace ce que votre site sert actuellement à /robots.txt.

  • Sauf là où vous en décidez autrement — des exemptions de chemins par site, pour que vous puissiez bloquer les crawlers IA partout sauf /blog.

  • Les requêtes qui ne ressemblent pas à un navigateur, par site. Six règles indépendantes, chacune son propre interrupteur et chacune désactivée par défaut — un interrupteur par règle pour que si quelque chose chez vous cesse de fonctionner, vous puissiez identifier quelle règle en est la cause :

    Deux garde-fous s'appliquent à toutes, et sont appliqués plutôt que laissés à votre charge :

    • Les deux règles dépendant de TLS ne sont écrites que dans les blocs server HTTPS. Les navigateurs ne font pas de HTTP/2 sans TLS, donc sur un bloc listen 80 simple, chaque requête est en HTTP/1.1 — y compris la redirection qu'un navigateur effectue en route vers HTTPS. Vos blocs port-80 et port-443 partagent généralement un server_name, donc le paramètre atteint les deux ; seul celui avec TLS reçoit ces règles. Les règles de forme d'en-tête fonctionnent en HTTP simple et sont écrites dans les deux.
    • /.well-known/ est toujours exempté dès qu'une règle est activée. C'est là que Let's Encrypt récupère son challenge HTTP-01, en HTTP/1.1 sans Accept et souvent sans User-Agent — sans l'exemption, votre certificat cesse de se renouveler des semaines plus tard.

Ce qu'une requête bloquée reçoit réellement

Un choix à l'échelle de l'hôte, dans Site settings. Ce ne sont pas des codes de statut interchangeables — chacun dit quelque chose de différent, et la différence compte surtout pour les clients que vous n'aviez pas l'intention de prendre :

OptionÀ quoi ça sert
403 Forbidden (par défaut)indique que le blocage était délibéré ; le seul sur lequel un humain pris par erreur peut agir
404 Not Founddissimule qu'il y a eu un blocage
410 Gonedemande aux crawlers bien élevés d'abandonner l'URL définitivement — préférez ceci au 403 quand vous écartez des crawlers plutôt que des attaquants
429 Too Many Requestsdit à un client poli de ralentir et de réessayer
418 I'm a teapotla blague de la RFC 2324. Ça fonctionne ; ce n'est simplement pas enregistré auprès de l'IANA, et NGINX l'envoie avec un corps vide
444 close connectionaucune réponse du tout ; le moins coûteux, mais indiscernable d'un serveur en panne
Tarpitrépond 403 mais fait couler le corps à un octet par seconde, pour que le client attende au lieu de passer à autre chose

Le tarpit est l'option la plus douce pour un faux positif — un client pris par erreur est ralenti, pas refusé — et la plus coûteuse pour un bot, dont la connexion reste inactive. Deux choses à savoir avant de le choisir : il retient aussi une de vos connexions worker pendant toute la durée, donc un flot de clients tarpités entre en concurrence avec les vrais visiteurs pour worker_connections ; et combien de temps cela dure réellement dépend de la façon dont NGINX choisit d'écrire un petit corps d'erreur, ce qui est noté dans TODO.md comme nécessitant une vérification contre un vrai serveur.

À partir de vos journaux, automatiquement

Chacun de ces éléments est un interrupteur indépendant sur le panneau « Automatic blocking » du Dashboard, et chacun ajoute un blocage de pare-feu temporaire qui expire de lui-même et est réajouté si le comportement persiste.

Ils s'exécutent sur un minuteur interne qui relit vos journaux d'accès SSH et NGINX toutes les minutes — mais uniquement tant que la TUI ou l'interface web est en cours d'exécution. L'une ou l'autre maintient le même calendrier, dans la même base de données, donc laisser l'interface web ouverte suffit ; rien n'est détecté quand aucune des deux n'est en cours d'exécution. Pour un serveur sans aucun processus stop-bots dessus, voir Unattended, from cron ci-dessous.

  • Scanners SSH et web : IP avec une pile de connexions SSH échouées, ou de nombreux chemins distincts en 404. Jamais une IP avec une connexion SSH réussie récente, ni une IP dans une plage IP publiée d'un crawler connu.
  • Crawlers falsifiés : tout ce qui prétend être Googlebot, Bingbot ou GPTBot depuis une adresse que l'opérateur de ce crawler ne publie pas. Le déguisement courant le moins coûteux qui soit, et les listes CIDR publiées tranchent la question. Inerte tant que ces listes n'ont pas été réellement récupérées.
  • Sondage de secrets exposés : une seule requête pour /.env, /.git/config, /wp-config.php et similaires est concluante à elle seule, donc cela ne nécessite aucun seuil. La liste intégrée omet délibérément les chemins qui sont légitimes quelque part — /wp-login.php, /wp-admin/, /xmlrpc.php, /phpmyadmin — car verrouiller votre propre administrateur serait pire que manquer un scanner que le détecteur de 404 attrape de toute façon. Ajoutez les vôtres avec set-probe-paths.
  • Honeypot : un chemin publié uniquement comme Disallow: dans le robots.txt généré et lié nulle part. L'atteindre signifie ignorer robots.txt, ce qu'aucune entité légitime ne fait par accident — le signal le plus fort ici, et le blocage le plus long. Nécessite que la génération de robots.txt soit activée pour fonctionner du tout.

Trois autres examinent comment un client se comporte plutôt que ce qu'il demande. Les trois sont désactivés par défaut, car chacun a un faux positif qu'il ne peut pas écarter seul — et tous les trois exemptent les crawlers de moteurs de recherche vérifiés, qui autrement correspondraient à chacun d'eux :

  • Ne récupère aucun asset : de nombreuses pages distinctes et pas une seule feuille de style, script ou image. Les navigateurs chargent ce qui va avec une page. N'attrapera pas un client API (il compte les chemins distincts, et un client API en touche peu) ni un visiteur récurrent bien mis en cache (un 304 compte comme un asset récupéré). Ne peut pas vous aider sur un site qui ne sert aucun asset du tout — une pure API JSON.
  • User agent rotatif : plusieurs identités depuis une même adresse. Considérablement affaibli par le NAT : une passerelle d'opérateur, de campus ou de bureau présente de nombreux vrais navigateurs sur une seule IP, et sans analyse des horodatages, il n'y a aucun moyen de distinguer cela d'un scraper qui fait tourner ses agents.
  • Crawle sans referer : de nombreuses pages profondes distinctes, jamais de Referer. Affaibli par Referrer-Policy: no-referrer et les outils de confidentialité ; le seuil de chemins distincts est ce qui le rend utilisable tout court.

Par adresse

  • Des pays entiers, via les listes CIDR agrégées d'IPdeny — bloquez des pays spécifiques, ou basculez en mode liste d'autorisation et bloquez tout le reste.
  • Des adresses connues comme malveillantes, via des listes tierces : FireHOL niveau 1, nœuds de sortie Tor et blocklist.de. Toutes désactivées par défaut.
  • Des hébergeurs entiers : AWS, Google Cloud et DigitalOcean publient leur espace d'adressage, et les visiteurs résidentiels ne naviguent pas depuis celui-ci. Ce sont des instruments grossiers et étiquetés comme tels — ils bloquent chaque visiteur hébergé là, y compris les points de terminaison VPN, les sorties d'entreprise et les clients API, pas seulement les bots. Désactivé par défaut, avec un avertissement quand vous en activez un.
  • Les adresses voisines, en option : quand plusieurs adresses dans un même IPv4 /24 sont signalées lors de la même passe, bloquez le /24. Désactivé par défaut — bloquer 256 adresses parce que trois se sont mal comportées est un dommage collatéral assumé. (IPv6 est différent et ne nécessite aucun interrupteur : une détection bloque toujours le /64, car un /64 est un LAN, la même chose qu'une seule adresse IPv4 représente. Bloquer la seule adresse qu'un attaquant IPv6 a utilisée n'arrêterait rien — il en a 2^64 autres.)
  • Tout le reste, à la main — ajoutez directement une règle d'autorisation ou de blocage IP/CIDR, ou utilisez l'écran Dynamic Protection pour bloquer définitivement une IP ou un user agent spécifique que vous avez repéré avant qu'il ne franchisse un seuil automatique.

Est-ce que ça fonctionne réellement ?

Tout ce qui précède est généré. Savoir si tout ou partie est en vigueur est une question distincte, et stop-bots status est ce qui y répond :``` stop-bots status

root@kitploit:~
Sept vérifications, et la première est celle qui vaut la peine : les règles générées sont-elles réellement dans le noyau, ou seulement sur le disque ? Un hôte réel a tourné pendant trois semaines avec 48 860 règles de drop dans `/etc/stop-bots/firewall.nft` et un ensemble de règles vide, parce qu'écrire le script et le charger sont deux étapes et que personne n'avait jamais regardé la seconde.

Le reste : l'ensemble de règles survivra-t-il à un redémarrage (`nftables.service` activé ?), le script correspond-il toujours aux règles, les blocs NGINX sont-ils appliqués, le service de console exécute-t-il le binaire qu'il nomme, y a-t-il de la place pour la base de données, et les détecteurs peuvent-ils lire leurs journaux.

Il se termine avec un code non nul si quelque chose est **CRITICAL**, ce qui en fait une vérification de supervision. `--quiet` n'affiche que ce qui nécessite attention, ce qui est la forme adaptée à cron :```
0 * * * * /usr/local/bin/stop-bots status --quiet

Un contrôle qui n'a pas pu s'exécuter — nft list nécessite root — rapporte UNKNOWN, jamais OK. Un contrôle de santé qui dit que tout va bien parce qu'il n'a pas pu regarder est pire que rien, parce qu'on y croit.

Le même rapport figure sur le Dashboard dans la console et dans la TUI, relevé toutes les heures par le cron interne plutôt qu'à chaque rendu : nft list sur un grand ensemble de règles représente des mégaoctets de texte.

Rien ne se produit sans vous

Chaque décision de pare-feu ci-dessus est générée, jamais appliquée automatiquement : render-firewall (ou la touche f du Dashboard) écrit un script iptables ou nftables que vous pouvez examiner et appliquer vous-même, et refuse d'en écrire un qui verrouillerait une session SSH actuellement connectée.

Trois choses peuvent l'appliquer pour vous, et toutes les trois nécessitent que vous le demandiez : la popup de rendu de la TUI (« apply after writing ») ou sa touche a, le panneau pare-feu de la console web (« run it after writing ») ou son bouton « Apply everything », et batch --apply depuis un crontab que vous avez écrit — voir Unattended, from cron. Aucune d'entre elles n'est un effet de bord de quoi que ce soit d'automatique : le cron interne génère le script et ne l'exécute jamais.

Il en va de même côté NGINX : modifier un paramètre ne change que ce qui serait écrit. Les paramètres de site affichent chaque site comme STALE jusqu'à ce que vous appliquiez.

Désactiver un détecteur ne supprime jamais les blocages qu'il a déjà ajoutés — ceux-ci expirent d'eux-mêmes. « Arrêter de détecter » et « annuler ce qui a été détecté » sont délibérément distincts ; le second est l'écran Dynamic Protection ou remove-firewall-rule.

Il existe aussi un simple décompte des journaux d'accès, indépendant du blocage : record-access-stats / list-access-stats comptent la fréquence d'apparition de chaque user agent dans les requêtes réussies (non erronées), afin que vous puissiez voir qui visite réellement en plus de qui est bloqué.

Unattended, from cron

stop-bots batch est une passe sur tout ce que la TUI fait à la main : rafraîchir chaque liste, analyser les journaux, écrire les règles de blocage NGINX et le script de pare-feu.```

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:~
Il ne dit rien quand tout a fonctionné, donc une exécution nocturne saine ne vous envoie pas de mail. Une étape échouée écrit sur stderr et définit un statut de sortie non nul, ce qui fait que cron vous en informe. Lancez-le une fois à la main avec `--verbose` d'abord — cela affiche une ligne par étape, et c'est le moyen le plus simple de voir ce qu'il fait réellement.

**`--apply` est ce qui lui fait appliquer quoi que ce soit.** Sans lui, `batch` écrit la configuration NGINX et le script de pare-feu puis s'arrête : la configuration ne fait rien tant qu'il n'y a pas de rechargement, un script ne fait rien tant qu'il n'est pas exécuté. C'est la valeur par défaut de ce projet partout, et elle le reste ici.

`batch` et un front-end de longue durée coexistent sans problème. La TUI, l'interface web et `batch` enregistrent tous ce qu'ils ont fait via les mêmes clés dans la même base de données, donc celui qui atteint une tâche en premier l'exécute et les autres constatent qu'elle n'est plus due — vous n'obtenez pas deux passes de détection, et le panneau « Scheduled tasks » du Dashboard montre ce qui s'est réellement passé plutôt que de prétendre que tout est en retard. Si vous laissez déjà l'interface web tourner, l'entrée nocturne `batch` est une ceinture et des bretelles plutôt qu'une nécessité ; si ce n'est pas le cas, c'est la seule chose qui maintient la détection à jour.

**Avec `--apply`, le garde-fou contre le verrouillage SSH peut refuser — et refuser signifie que rien n'est appliqué.** Il refuse si les règles bloqueraient un client actuellement connecté, *et* si aucun journal SSH n'a pu être lu du tout, car alors la vérification n'a pas pu s'exécuter. Le `render-firewall` interactif affiche seulement une note dans ce second cas, en partant du principe qu'un humain surveille le terminal ; depuis cron, personne ne le fait. **Passez `--ssh-log` explicitement** : cron s'exécute en root donc `/var/log/auth.log` se lit généralement bien, mais sur un hôte journald uniquement, `journalctl` sous cron peut revenir vide, ce qui est exactement le cas pour lequel il refuse. `--force` outrepasse le garde-fou si vous le voulez vraiment.

L'échec d'une étape n'arrête jamais les autres, et les moitiés NGINX et pare-feu sont indépendantes — un rechargement NGINX échoué laisse quand même le pare-feu appliqué, et inversement.

`batch` enregistre chaque étape selon le même planning que le cron interne de la TUI utilise, donc les deux s'accordent sur ce qui a déjà été exécuté au lieu de le faire tous les deux, et le panneau « Scheduled tasks » du Dashboard montre ce que votre vrai cron a fait.

# L'interface web

`stop-bots web` sert les mêmes cinq écrans dans un navigateur.```
stop-bots web

Il se lie à 127.0.0.1:8787 — accessible uniquement depuis cette machine — et affiche un mot de passe généré une seule fois, au premier lancement. Accédez-y depuis votre ordinateur portable via un tunnel SSH :``` ssh -L 8787:127.0.0.1:8787 your-server

root@kitploit:~
puis ouvrez <http://127.0.0.1:8787/>.

![Le tableau de bord de la console web : les pastilles d'état et les deux boutons à l'échelle de l'hôte dans l'en-tête, la politique, le géo-blocage et les flux tiers dans une colonne, le blocage automatique et les tâches planifiées dans l'autre](https://assets.kitploit.com/production/public/readmes/55148/73bbcc92f0f3d2c9d0586bd71ad18f1b4d582fa59824b4f5e3c97e08575f5070/bb45db648f6a59192f56b1e14a019f50f0816bff651766316c377cbe79f700b6-display-v1.webp)

La console suit le réglage clair ou sombre du système d'exploitation, avec un bouton bascule dans
l'en-tête ; les captures d'écran du TUI ci-dessus correspondent au thème sombre, celles-ci au thème clair. Les touches que
le TUI utilise fonctionnent ici aussi : `1`–`4` changent d'écran, `/` place le focus sur le champ de recherche, `?` ouvre l'aide.

![La page Dynamic Protection de la console web : les connexions SSH échouées et les principaux user agents, chacun avec une barre de comptage et une étiquette d'état, et un bouton de blocage ou de déblocage par ligne](https://assets.kitploit.com/production/public/readmes/55148/090d4d2151eb00a69781c44351abe10f268d8031816199b9aeb5b4d2cddfc5f5/52a05387d1227288e7f45ece3c33e4af17957d8e9e73fb7c0213d64c49dc7419-display-v1.webp)

Trois actions à l'échelle de l'hôte se trouvent dans l'en-tête, sous forme de boutons dans le navigateur et de touches
uniques dans le TUI :

- **Tout mettre à jour** (`u`) télécharge chaque liste de bots, chaque plage d'IP de crawlers, chaque
  flux de réputation *activé* et chaque pays *sélectionné* — le même ensemble que `stop-bots batch`
  récupère, à partir du même plan. L'échec d'une source n'arrête pas les autres, et rien n'est
  appliqué tant que quelque chose ne le fait pas.
- **Tout appliquer** (`a`) écrit et recharge la configuration NGINX, puis écrit et exécute le
  script de pare-feu. Les deux plans sont indépendants : quel que soit celui qui échoue, l'autre passe quand même
  son tour, car un hôte à moitié appliqué vaut mieux qu'un hôte où une erreur de syntaxe NGINX a aussi laissé
  le pare-feu obsolète.
- **Web Access** (`w`) configure NGINX pour servir la console elle-même — voir
  [Derrière NGINX](#behind-nginx-a-subdomain-or-a-path-prefix).

## En tant que service (Debian)```
sudo stop-bots install web

Écrit /etc/systemd/system/stop-bots-web.service, crée /var/lib/stop-bots (0700 — il contient le hachage du mot de passe de la console) et /etc/stop-bots, génère un mot de passe s'il n'y en a pas, puis active et démarre l'unité.

--dry-run affiche l'intégralité du plan et ne modifie rien. C'est la seule commande du projet qui démarre un démon, alors commencez par là. --prefix <dir> écrit la même arborescence quelque part où vous pouvez la lire sans être root. Si l'unité existe déjà et que vous l'avez modifiée, l' installateur s'arrête et le signale plutôt que de remplacer votre modification ; --force si c'est bien ce que vous voulez.

Le service s'exécute en tant que root, car la console réécrit /etc/nginx, écrit le script du pare-feu, et exécute nginx -t et systemctl reload nginx. Il n'existe pas de découpage non privilégié qui laisse l'ensemble des fonctionnalités intact. L'unité porte le durcissement qui survit à cette exigence et un commentaire indiquant quel durcissement a été omis et pourquoi.

L'adresse d'écoute, la liste d'autorisation des hôtes et le préfixe de chemin ne sont délibérément pas dans l'unité — le serveur en cours d'exécution les relit depuis la base de données, donc les mettre dans ExecStart leur donnerait deux sources de vérité. Modifiez-les avec stop-bots web --save ... et redémarrez.

Une chose change une fois que cela s'exécute en tant que root : la tâche quotidienne RenderFirewall du cron interne peut désormais écrire /etc/stop-bots/firewall.nft, ce qu'elle ne pouvait pas faire lorsque vous exécutiez la console à la main en tant que vous-même. Rien n'applique ce script — l'exécuter reste à votre charge.

Seul Debian est vérifié, car c'est ce qui a été testé ; l'unité est très probablement correcte sur toute distribution systemd, mais le chemin de journal SSH qu'elle suppose est celui de Debian.

L'exposer

Lier autre chose que loopback nécessite un second drapeau délibéré, car cette console peut réécrire le pare-feu et la configuration NGINX de l'hôte sur lequel elle s'exécute :``` stop-bots web --bind 0.0.0.0:8787 --expose --allowed-hosts admin.example.com --save

root@kitploit:~
`--allowed-hosts` n'est pas optionnel en pratique : une requête portant un nom d'hôte qui n'est pas
listé est refusée. C'est ce qui fait échouer le DNS rebinding contre la console, et c'est
pourquoi un serveur exposé atteint par nom a besoin que le nom soit explicitement indiqué.

Placez-le derrière NGINX avec TLS — le même NGINX que cet outil protège. Si vous le faites, et que le
proxy définit `X-Forwarded-For`, indiquez à la console qu'elle peut croire cet en-tête, sinon elle ne peut pas
déterminer de quelle adresse une requête provient réellement :```
stop-bots web --bind 127.0.0.1:8787   # and set web:trust_forwarded_for

Derrière TLS, définissez aussi web:secure_cookie. Sans cela, un navigateur enverra également le cookie de session à une URL http:// pour le même hôte.

web:trust_forwarded_for compte plus qu'il n'y paraît. Sans lui, chaque requête derrière un proxy arrive depuis 127.0.0.1, donc la console ne peut pas distinguer un client d'un autre — ce qui signifie qu'un flot de tentatives de connexion partage le même compartiment de limitation que vous, et le garde-fou qui vous empêche de bloquer votre propre adresse n'a rien avec quoi comparer. Avec lui, les deux fonctionnent par client.

Derrière NGINX : un sous-domaine, ou un préfixe de chemin

La console peut configurer cela pour vous, et le TUI aussi (w sur le Dashboard). Les deux écrivent la configuration NGINX, enregistrent le préfixe de chemin et ajoutent le nom d'hôte à la liste d'autorisation — les trois éléments qui doivent concorder, car un préfixe manquant fait sortir chaque lien du bloc location et un nom d'hôte manquant transforme chaque requête en 403. Les deux valident avec nginx -t avant que la configuration puisse prendre effet, la restaurent en cas d'échec, et n'enregistrent la nouvelle adresse qu'une fois validée.

Deux modes, et path est celui par défaut pour une raison : il ajoute un bloc location à un site que vous avez déjà, donc la console hérite du certificat de ce site. Un sous-domaine a besoin du sien, et tant que certbot --nginx -d <host> n'a pas été exécuté, le formulaire de mot de passe et le cookie de session de cette console traversent le réseau en clair.

Le reste de cette section est la même chose à la main, ce qui vaut la peine d'être lu une fois même si vous utilisez le panneau — le piège de la barre oblique finale ci-dessous est l'erreur qu'il existe pour prévenir.

Un sous-domaine est le déploiement le plus simple, et celui à choisir si vous le pouvez :```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` | `http://localhost:8080` | URL du serveur cible |
| `-t` | `--token` | `TOKEN` | - | Jeton d'authentification |
| `-o` | `--output` | `FILE` | - | Chemin du fichier de sortie |
| `-v` | `--verbose` | - | `false` | Activer la sortie détaillée |
| `-q` | `--quiet` | - | `false` | Supprimer la sortie non essentielle |
| `--timeout` | - | `SECONDS` | `30` | Délai d'expiration de la requête en secondes |
| `--retry` | - | `COUNT` | `3` | Nombre de tentatives en cas d'échec |
| `--insecure` | - | - | `false` | Ignorer la vérification du certificat TLS |
| `--proxy` | - | `URL` | - | URL du proxy à utiliser |
| `--config` | - | `FILE` | `~/.tool/config.yaml` | Chemin du fichier de configuration |
| `--no-color` | - | - | `false` | Désactiver la sortie colorée |
| `--debug` | - | - | `false` | Activer la journalisation de débogage |

### Exemples

```bash
# Exécution de base
tool scan --target example.com

# Avec jeton d'authentification
tool scan --target example.com --token "your-api-token"

# Sortie vers un fichier
tool scan --target example.com --output results.json

# Mode détaillé avec délai d'expiration personnalisé
tool scan --target example.com --verbose --timeout 60

# Utilisation d'un proxy
tool scan --target example.com --proxy "http://proxy.example.com:8080"

# Ignorer la vérification TLS (non recommandé en production)
tool scan --target example.com --insecure

Fichier de configuration

L'outil prend en charge un fichier de configuration YAML pour définir les options par défaut :

root@kitploit:~
# ~/.tool/config.yaml
server: "http://localhost:8080"
token: "your-api-token"
timeout: 30
retry: 3
verbose: false
output: "results.json"

Sortie

L'outil génère une sortie structurée dans plusieurs formats :

Format JSON

root@kitploit:~
{
  "target": "example.com",
  "timestamp": "2024-01-15T10:30:00Z",
  "status": "completed",
  "findings": [
    {
      "id": "FINDING-001",
      "severity": "high",
      "title": "Exemple de vulnérabilité",
      "description": "Description détaillée de la vulnérabilité",
      "remediation": "Étapes pour corriger le problème"
    }
  ]
}

Format texte

root@kitploit:~
[+] Cible : example.com
[+] Statut : Terminé
[+] Constats : 1

[HIGH] FINDING-001 : Exemple de vulnérabilité
  Description : Description détaillée de la vulnérabilité
  Remédiation : Étapes pour corriger le problème

Format CSV

root@kitploit:~
id,severity,title,description
FINDING-001,high,Exemple de vulnérabilité,Description détaillée de la vulnérabilité

Codes de sortie

CodeSignification
0Succès
1Erreur générale
2Arguments de ligne de commande invalides
3Échec de la connexion au serveur
4Échec d'authentification
5Délai d'expiration de la requête dépassé
6Permission refusée
7Fichier introuvable
8Format de sortie non pris en charge

Dépannage

Problèmes courants

Connexion refusée

  • Vérifiez que le serveur est en cours d'exécution et accessible
  • Vérifiez l'URL du serveur et le numéro de port
  • Assurez-vous qu'aucun pare-feu ne bloque la connexion

Échec d'authentification

  • Vérifiez que votre jeton est valide et non expiré
  • Assurez-vous que le jeton dispose des permissions requises
  • Vérifiez que le jeton est correctement formaté

Délai d'expiration de la requête dépassé

  • Augmentez la valeur de --timeout
  • Vérifiez la connectivité réseau
  • Vérifiez que le serveur n'est pas surchargé

Permission refusée

  • Vérifiez les permissions du fichier de sortie
  • Assurez-vous de disposer des privilèges nécessaires
  • Essayez d'exécuter avec des permissions élevées si nécessaire

Mode débogage

Activez la journalisation de débogage pour obtenir des informations détaillées :

root@kitploit:~
tool scan --target example.com --debug

Cela affichera des informations détaillées sur les requêtes, les réponses et les erreurs.``` stop-bots web --allowed-hosts stopbots.example.com --save

root@kitploit:~
**Un préfixe de chemin fonctionne aussi**, mais la console doit en être informée — elle doit
générer chaque lien, action de formulaire, redirection et chemin de cookie avec le préfixe déjà
inclus, et elle ne peut pas le deviner :```
stop-bots web --base-path /stop-bots --allowed-hosts example.com --save

| -s | --server | string | URL du serveur C2 (par défaut : http://127.0.0.1:8080) | | -p | --password | string | Mot de passe pour l'authentification du client | | -k | --key | string | Clé de chiffrement pour la communication | | -i | --interval | int | Intervalle de beacon en secondes (par défaut : 5) | | -j | --jitter | float | Pourcentage de gigue pour l'intervalle de beacon (par défaut : 0.2) | | -t | --timeout | int | Délai d'expiration de la requête en secondes (par défaut : 30) | | -r | --retries | int | Nombre de tentatives de reconnexion (par défaut : 3) | | -d | --debug | bool | Activer la journalisation de débogage | | -v | --version | bool | Afficher la version et quitter | | -h | --help | bool | Afficher le message d'aide et quitter |

Exemples

root@kitploit:~
# Démarrer le client avec les paramètres par défaut
./client

# Se connecter à un serveur C2 spécifique avec un mot de passe
./client -s https://c2.example.com:8443 -p mypassword

# Définir un intervalle de beacon de 10 secondes avec 30% de gigue
./client -i 10 -j 0.3

# Activer la journalisation de débogage
./client -d

Configuration

Le client peut être configuré à l'aide d'un fichier de configuration ou de variables d'environnement. Le fichier de configuration est recherché dans les emplacements suivants :

  1. ./config.yaml
  2. $HOME/.config/client/config.yaml
  3. /etc/client/config.yaml

Variables d'environnement

VariableDescription
CLIENT_SERVERURL du serveur C2
CLIENT_PASSWORDMot de passe pour l'authentification du client
CLIENT_KEYClé de chiffrement pour la communication
CLIENT_INTERVALIntervalle de beacon en secondes
CLIENT_JITTERPourcentage de gigue pour l'intervalle de beacon
CLIENT_TIMEOUTDélai d'expiration de la requête en secondes
CLIENT_RETRIESNombre de tentatives de reconnexion
CLIENT_DEBUGActiver la journalisation de débogage

Exemple de fichier de configuration

root@kitploit:~
server: https://c2.example.com:8443
password: mypassword
key: myencryptionkey
interval: 10
jitter: 0.3
timeout: 30
retries: 3
debug: false

Compilation à partir des sources

Prérequis

  • Go 1.21 ou supérieur
  • Make (facultatif, mais recommandé)

Étapes de compilation

root@kitploit:~
# Cloner le dépôt
git clone https://github.com/example/client.git
cd client

# Compiler le client
make build

# Ou compiler directement avec Go
go build -o client ./cmd/client

# Compiler pour plusieurs plateformes
make build-all

Compilation croisée

root@kitploit:~
# Compiler pour Linux (amd64)
GOOS=linux GOARCH=amd64 go build -o client-linux-amd64 ./cmd/client

# Compiler pour Windows (amd64)
GOOS=windows GOARCH=amd64 go build -o client-windows-amd64.exe ./cmd/client

# Compiler pour macOS (amd64)
GOOS=darwin GOARCH=amd64 go build -o client-darwin-amd64 ./cmd/client

Tests

root@kitploit:~
# Exécuter tous les tests
make test

# Exécuter les tests avec couverture
make test-coverage

# Exécuter les tests d'intégration
make test-integration

Sécurité

  • Toutes les communications sont chiffrées à l'aide d'AES-256-GCM
  • L'authentification est effectuée à l'aide de mots de passe hachés avec bcrypt
  • Le client prend en charge TLS pour les connexions sécurisées
  • Les clés de chiffrement ne sont jamais stockées en texte clair sur le disque

Avertissement

Cet outil est fourni à des fins éducatives et de recherche en sécurité uniquement. Les auteurs ne sont pas responsables de toute utilisation abusive ou de tout dommage causé par ce logiciel. Utilisez-le de manière responsable et conformément aux lois applicables.

Licence

Ce projet est sous licence MIT - voir le fichier LICENSE pour plus de détails.

Remerciements

  • Go - Le langage de programmation utilisé
  • Cobra - Bibliothèque CLI
  • Viper - Bibliothèque de configuration```nginx location /stop-bots/ { proxy_pass http://127.0.0.1:8787; # NO trailing slash proxy_set_header Host $host; }
root@kitploit:~
**Le slash final dans `proxy_pass` est important, et son absence est toute l'astuce.**
Sans lui, NGINX transmet le chemin complet et `stop-bots` voit
`/stop-bots/whatever`, ce qu'il sert et génère désormais. *Avec* un slash
final, NGINX supprime le préfixe — et le navigateur résout alors les liens de la page
par rapport à la racine du domaine, atterrit en dehors du bloc `location`, et tout renvoie une 404. Aucun
soin côté serveur ne peut corriger cela, donc le préfixe doit survivre au
proxy.

Rien ne l'impose de l'extérieur, mais l'échec est bruyant plutôt que subtil : avec le
préfixe configuré, une requête sans préfixe est une simple 404 plutôt qu'une page qui
fonctionne à moitié.

## Ce qu'il ne fera pas

Deux choses manquent volontairement, et l'écran d'aide le dit avec les raisons :

- **Il ne débloquera pas quelque chose qu'une liste téléchargée a bloqué** — le prochain rafraîchissement de cette
  liste l'annulerait silencieusement.
- **Il ne changera pas son propre mot de passe.** Utilisez `stop-bots web --set-password` sur l'hôte.

Il refuse également de bloquer l'adresse depuis laquelle vous êtes connecté, ce qui supprimerait la
console que vous utiliseriez pour l'annuler.

**Il y en avait trois auparavant.** Appliquer le script de pare-feu était la troisième, au motif que
l'exécuter est la seule opération qui peut retirer l'hôte du réseau. C'est désormais
disponible — « Apply everything » sur le Dashboard (`a` dans la TUI), ou la case « run it after
writing » dans le panneau du pare-feu — parce que la garde qui le rend sûr depuis cron le rend sûr depuis un
bouton : les règles sont vérifiées par rapport aux clients actuellement connectés en SSH, dans
l'ordre où le script lui-même les évaluera, et une règle qui en bloquerait un est un
refus plutôt qu'un avertissement. Lancez la console avec `--no-apply` pour retrouver l'ancien
comportement en écriture seule.

Les tentatives de connexion sont limitées. Non pas parce que le mot de passe est devinable — il est généré,
144 bits — mais parce que vérifier un mot de passe exécute Argon2id, et laisser un appelant non authentifié
le solliciter aussi vite qu'il peut envoyer des requêtes est un déni de service contre l'hôte que cet outil
est censé protéger. Dix tentatives erronées sont gratuites ; au-delà, un client ralentit
exponentiellement, et un plafond global borne le CPU quel que soit le nombre d'adresses d'où
proviennent les tentatives.

## Exécuter NGINX dans un conteneur

Si NGINX est dans Docker et que sa configuration est sur un bind mount, `systemctl reload nginx` ne recharge
rien. Pointez les deux commandes vers le conteneur à la place — cela s'applique aussi au CLI et à la
TUI :```
stop-bots set-nginx-commands \
  --test   "docker exec web nginx -t" \
  --reload "docker exec web nginx -s reload"

La commande est divisée en mots et exécutée directement. Elle ne passe jamais par un shell, donc ;, | et $VAR sont des caractères ordinaires plutôt que de la syntaxe.

Contribuer

L'organisation du code, la façon dont il est testé et les règles selon lesquelles il est écrit se trouvent dans CONTRIBUTING.md. Le processus de publication est dans RELEASING.md.

Contact

Vous pouvez me contacter à [email protected].

Licence

Copyright (C) 2026 Marko Ivankovic

Ce programme est un logiciel libre : vous pouvez le redistribuer et/ou le modifier selon les termes de la GNU Affero General Public License telle que publiée par la Free Software Foundation, soit la version 3 de la Licence, soit (à votre choix) toute version ultérieure.

Consultez le fichier LICENSE pour le texte complet de la Licence.

Vous ne pouvez pas utiliser un logiciel sous AGPL ?

Une licence alternative n'est PAS disponible.

Télécharger l’outil
RègleÉcarte, outre les bots
HTTP/1.0 et HTTP/1.1les crawlers et clients API qui ne parlent pas HTTP/2
Pas d'en-tête Acceptcertains clients API n'en envoient aucun
Pas d'Accept-Languageles outils de confidentialité le suppriment
User-Agent vide/absentles scripts et vérifications de santé l'omettent souvent
Host est une IP nueempêche d'atteindre le site par IP
TLS 1.0 / 1.1uniquement les clients très anciens