Skip to main contentSkip to footer

Bloquer avec l'agent Linux

Le flux communautaire dans le noyau et les adresses que cet hôte bannit lui-même : les deux sortes d'ensembles et leurs durées de vie, comment un bannissement local commence et finit, l'escalade avec de vrais chiffres, la chaîne dans le noyau, les deux interrupteurs mode et ban.enabled, et comment on lève un bannissement ou tout à la fois.

Le flux communautaire

C'est la partie que la page Blocage au niveau du réseau décrit sous forme de script shell. L'agent fait la même chose, avec les parties qu'on rate facilement en l'écrivant soi-même déjà réglées : une requête conditionnelle par liste pour qu'une liste inchangée ne coûte rien, une vérification de taille avant que quoi que ce soit ne passe en production, une bascule atomique pour qu'il n'y ait jamais de fenêtre avec un ensemble vide, et des règles liées aux ports pour qu'un attaquant web n'enferme personne hors de SSH.

ListeEnsemble du noyauPorts concernés par la règle
sshrip-ssh, rip-ssh-v6depuis lists.ssh.ports
mailrip-mail, rip-mail-v625, 465, 587, 110, 995, 143, 993
webrip-web, rip-web-v680, 443
ftprip-ftp, rip-ftp-v621
edgerip-edge, rip-edge-v6tous les ports, volontairement
grouprip-group, rip-group-v6tous les ports, voir ci-dessous

La fréquence de récupération du flux dépend de votre forfait, et c'est le serveur qui en décide, pas l'agent. Sur un serveur sous licence, l'intervalle est de 15 minutes avec une confiance minimale de 75 à partir de Professional, et d'une heure avec une confiance minimale de 90 sur Contributor. Business et Enterprise se comportent comme Professional. L'agent demande quelles valeurs s'appliquent à cet hôte et suit la réponse : une montée de forfait prend donc effet sans que personne ne modifie un fichier. La réponse est gardée en cache jusqu'à 24 heures, et seul un état api_key, license ou reputation ouvert le fait redemander à chaque passage : un changement de forfait arrive donc sur l'hôte en un jour au plus. Il n'existe aucune clé de configuration pour l'intervalle, et une clé que vous inventeriez pour cela arrête l'agent avec le code 2.

Deux règles s'ajoutent par-dessus. Une liste récupérée il y a moins de 15 minutes n'est pas récupérée de nouveau, car c'est la durée pendant laquelle le serveur la garde en cache. Lancer sync à la main est donc toujours permis et jamais nuisible. Et chaque récupération est conditionnelle : une liste inchangée répond 304 et coûte une requête sans transfert, et c'est pourquoi un intervalle court est économique des deux côtés.

La liste de groupe

Une clé dans un groupe reçoit une sixième liste, récupérée en json avec le flux communautaire. Chaque adresse est rejetée sur tous les ports dans les ensembles rip-group et rip-group-v6, quel que soit le service que cet hôte expose. Une clé sans groupe ne change rien : l'ensemble reste vide, et status affiche group=none.

La liste blanche du groupe, si elle en porte une, est lue dans la même requête et écrite dans /var/lib/reportedip-agent/group-whitelist, au format de whitelist.conf avec chaque note en commentaire. Ne modifiez pas ce fichier à la main, la synchronisation suivante le réécrit. Elle est appliquée dans le même passage aux trois endroits où une liste blanche agit : l'ensemble de liste blanche du noyau, le filtre de chaque liste et le filtre de signalement du service de surveillance, une couche de plus à côté de la whitelist.conf propre de cet hôte et de sa liste blanche automatique. Une clé qui quitte son groupe perd le fichier à la synchronisation suivante.

whitelist list et status affichent les entrées du groupe sur des lignes marquées group:, avec leurs notes. status nomme aussi le groupe et sa taille à côté de la ligne du compte et affiche le nombre d'entrées de la liste de groupe sous les listes comme pour toute autre. Voir Groupes pour ce qu'est un groupe, les limites par formule, la liste blanche et le webhook côté portail.

Blocage

L'agent écrit deux choses très différentes dans le noyau, et qui vient de fail2ban les confond généralement la première semaine. Elles ont des origines différentes, des durées de vie différentes et des interrupteurs différents, il vaut donc la peine de les séparer une fois pour de bon.

Deux sortes d'ensembles, deux durées de vie

Community BlacklistDétections locales
Ensemblesrip-ssh, rip-mail, rip-web, rip-ftp, rip-edge, rip-group, et un ensemble -v6 pour chacunrip-local et rip-local-v6
D'où viennent les adressesDe chaque membre de la communauté qui signale, filtrées par votre confidenceUniquement des journaux de cet hôte
Comment une entrée arriveL'ensemble entier est remplacé à chaque passage du fluxUne adresse à la fois, quand un seuil est atteint
Comment une entrée disparaîtÀ la bascule suivante, quand le flux ne la liste plusLe noyau la fait expirer quand son propre délai d'expiration est écoulé
Délai d'expiration par entréeaucunoui, c'est toute la conception
Interrupteurmodeban.enabled, et mode par-dessus
Nécessite une licenceoui, c'est la partie payéenon

Comment un bannissement local commence et comment il finit

Un bannissement commence quand le compteur d'un détecteur pour une adresse dépasse le seuil de sa source d'événement. Ce qui se passe alors, dans l'ordre :

  1. La liste blanche est vérifiée en premier, avant même que l'on demande autre chose. Une adresse en liste blanche ne laisse aucune trace : vous ne trouverez donc jamais votre propre plage d'administration dans reportedip-agent ban list en vous demandant si elle a été bloquée. La vérification indique quelle couche a répondu : une plage réservée interne, une des adresses propres de cet hôte, ou votre fichier.
  2. Le registre des bannissements, /var/lib/reportedip-agent/bans.json, est interrogé pour la durée. Il retient l'adresse, la date d'expiration, le nombre de bannissements tombés dans la fenêtre de mémoire, le début du dernier, la source et les catégories. Le fichier est écrit avant l'entrée dans le noyau : un plantage juste après l'écriture dans le noyau ne peut donc pas perdre l'enregistrement qui lève le bannissement.
  3. L'adresse entre dans rip-local avec cette durée comme délai d'expiration par entrée. Le noyau la fait expirer. Il n'y a pas de minuterie de nettoyage, pas de tâche cron et pas de file de débannissement, et c'est pour cela qu'un agent planté ou supprimé ne laisse aucun blocage permanent.
  4. Une ligne part dans le journal avec l'adresse, la durée, la source, le nombre de bannissements de cette adresse dans la fenêtre, l'écart entre la ligne de journal et l'entrée dans le noyau, et les deux commandes qui annulent tout cela.

Un bannissement en cours n'est jamais raccourci. Quand une nouvelle occurrence arrive pour une adresse déjà bannie, rien ne se passe : ce n'est pas non plus une escalade, car l'escalade compte les bannissements et non les occurrences, exactement comme la jail recidive qu'elle remplace. Une adresse déjà bloquée ne peut pas être bloquée une seconde fois. Cette règle garde aussi la période de transition honnête, quand l'agent voit une attaque deux fois, une fois comme ligne brute de auth.log et une fois comme ligne de bannissement de fail2ban.log.

Une ligne de journal rejouée ne produit pas de bannissement non plus. Une occurrence dont l'horodatage n'est pas plus récent que le dernier bannissement de cette adresse est une relecture après un arrêt brutal et non une nouvelle infraction, et le chemin de signalement a la même protection dans son fichier de déduplication.

L'état survit à plus qu'un redémarrage. Avec ban.enabled: true, chaque synchronisation compare bans.json à ce que le noyau détient réellement et remet ce qui manque, avec le temps restant :

  • Après un redémarrage de la machine, c'est la totalité, car ni un délai d'expiration ipset ni l'ensemble lui-même ne survit à un redémarrage. C'est pourquoi le service de synchronisation est activé pour multi-user.target et tourne après chaque service de pare-feu.
  • En fonctionnement normal, c'est ce qui a emporté l'ensemble : un firewall-cmd --reload, un csf -r, un ipset flush. Les entrées que le noyau détient encore ne sont pas touchées, l'écart est donc une partie d'un intervalle de synchronisation et non le reste du bannissement. Le journal dit explicitement quand des entrées manquaient sous des bannissements actifs, car cela signifie que quelque chose a modifié l'ensemble sous l'agent.
  • Un enregistrement expiré ne revient jamais. L'attaquant d'hier n'est pas une raison de couper quelqu'un aujourd'hui.
  • La liste blanche est revérifiée à chaque restauration. Elle peut avoir grandi pendant que l'hôte était arrêté, et une adresse que vous avez mise en liste blanche hier ne doit pas être rebloquée par un enregistrement de la veille.

L'escalade, avec de vrais chiffres

Le premier bannissement dure time_minutes. Chaque récidive dans la fenêtre de mémoire le multiplie par escalate, et max_time_minutes le plafonne. Avec les valeurs par défaut (30 minutes, multiplicateur 4, plafond d'une semaine), une adresse qui revient sans cesse suit ce chemin :

BannissementCalculDurée
1ertime_minutes30 minutes
2e30 × 42 heures
3e120 × 48 heures
4e480 × 432 heures
5e1920 × 4128 heures, cinq jours et huit heures
6e et suivantsce serait 512 heures, plafonné7 jours, la valeur de max_time_minutes

La chaîne dans le noyau

Avec le moteur ipset, l'agent possède exactement une chaîne, rip-blacklist, et un saut vers elle. Une synchronisation reconstruit la chaîne dès que son empreinte (la configuration et la chaîne telle que le noyau l'affiche) diffère, son contenu est donc toujours ce que dit la configuration ; sinon elle laisse la chaîne en place, pour que les compteurs de paquets continuent de compter. Le saut n'est inséré à la position 1 de INPUT que s'il n'y est pas déjà.

bash
# What a sync builds, in this order:
iptables -N rip-blacklist
iptables -F rip-blacklist
iptables -A rip-blacklist -m set --match-set rip-whitelist src -j RETURN
iptables -A rip-blacklist -m set --match-set rip-local src -j DROP
iptables -A rip-blacklist -p tcp --dport 22 \
         -m set --match-set rip-ssh src -j DROP
iptables -A rip-blacklist -p tcp -m multiport --dports 25,465,587,110,995,143,993 \
         -m set --match-set rip-mail src -j DROP
iptables -A rip-blacklist -p tcp -m multiport --dports 80,443 \
         -m set --match-set rip-web src -j DROP
iptables -A rip-blacklist -m set --match-set rip-edge src -j DROP
iptables -A rip-blacklist -m set --match-set rip-group src -j DROP

# Only with a scan source in the config: a SYN to a port this host
# does not listen on is logged, at most ten a minute. Listening ports
# and the passive range of a running FTP server return first, then any
# port a socket listens on at this very moment.
iptables -N rip-blacklist-scan
iptables -A rip-blacklist-scan -p tcp -m multiport --dports 21,22,25,80,443,40110:40210 -j RETURN
iptables -A rip-blacklist-scan -p tcp -m socket --nowildcard -j RETURN
iptables -A rip-blacklist-scan -m limit --limit 10/min --limit-burst 20 \
         -j LOG --log-prefix "rip-scan: "
iptables -A rip-blacklist -p tcp --syn -j rip-blacklist-scan

iptables -I INPUT 1 -j rip-blacklist

La liste blanche est la première règle et elle renvoie, elle n'est pas la dernière règle. Un RETURN avant tout le reste signifie qu'une adresse en liste blanche quitte la chaîne avant qu'aucun ensemble ne soit consulté : elle passe donc au-dessus de chaque bannissement, y compris un bannissement déjà présent dans rip-local. C'est ce qui fait de whitelist add une véritable sortie de secours, sans synchronisation et sans redémarrage. Une liste blanche placée à la fin serait une liste d'exceptions qui arrivent trop tard, et sur un hôte où vous vous êtes enfermé dehors, « trop tard » est tout le problème.

La règle des bannissements locaux n'est liée à aucun port, car un hôte qui a attaqué votre serveur de courrier n'a rien à faire sur le port 22 non plus. Les règles de ssh, mail, web et ftp sont liées aux ports : une adresse de la liste web est donc rejetée sur 80 et 443 et peut toujours atteindre SSH. C'est voulu : une adresse partagée, un NAT d'opérateur ou un proxy compromis dans la liste web ne doit pas enfermer un administrateur hors de la machine. Seuls edge et group s'appliquent à tous les ports : pour edge, c'est ce que signifie la catégorie qui est derrière, pour group, c'est le sens même d'un bannissement partagé.

Avec le moteur nftables, la forme est la même en natif : une table inet reportedip, une chaîne accrochée à input avec la priorité -10 et la politique accept, d'abord les deux règles return de la liste blanche, puis rip-local, puis les listes du flux avec leurs ports. Les ensembles de liste blanche sont des ensembles d'intervalles pour pouvoir contenir des plages CIDR ; les ensembles locaux portent l'option timeout, que les deux outils exigent sur l'ensemble avant qu'un élément puisse porter un délai d'expiration.

En mode: log, les mêmes règles sont construites, et le verdict est une ligne de journal à débit limité (six par minute, avec le préfixe rip-<list>:) au lieu de DROP. Tout le reste est identique, et c'est pourquoi le mode journal est une vraie répétition et non une simulation.

mode et ban.enabled sont deux interrupteurs

C'est le malentendu le plus fréquent, il a donc droit à son propre paragraphe. mode décide de ce que les règles font. ban.enabled décide si vos propres détections deviennent un jour une entrée. Par défaut, les deux sont actifs (mode: drop, ban.enabled: true). Avec ban.enabled: false, mode: drop applique la liste communautaire et rien de vos propres détections.

modeban.enabledListe communautaireVos propres détections
logfalseCorrespondances journalisées, rien n'est rejetéSignalées à la communauté, pas bloquées localement
logtrueCorrespondances journaliséesEnregistrées dans rip-local et visibles dans ban list, journalisées au lieu d'être rejetées
dropfalseRejetéeSeulement signalées. C'est un état permanent parfaitement sensé.
droptrueRejetéeRejetées aussi, avec escalade. La configuration complète.
offpeu importeRien dans le chemin des paquets : le saut est retiré ; avec ipset la chaîne reste avec ses règles, avec nftables la chaîne est suppriméeEnregistrées dans le registre, sans effet

off est l'interrupteur d'urgence et il est honnête là-dessus. Il retire ce qui accroche la chaîne au chemin des paquets, jusqu'à cinq fois pour attraper les sauts en double, et échoue bruyamment si un saut survit, car dire « off » et continuer de rejeter est pire qu'une erreur. Avec nftables, la chaîne elle-même est supprimée. Les ensembles gardent leurs entrées avec les deux moteurs : revenir en arrière ne demande donc aucun téléchargement complet.

Un bannissement manuel ignore volontairement les deux interrupteurs : reportedip-agent ban add fonctionne même avec ban.enabled: false, car c'est un acte délibéré d'un opérateur, comme l'était fail2ban-client set banip. La liste blanche continue de s'appliquer, et sur un hôte sans moteur de pare-feu la commande refuse.

Passer de log à drop

bash
# 1. What would have been dropped? The rules already match in
#    log mode, so ask the kernel log.
journalctl -k --since "24 hours ago" | grep -c "rip-"
journalctl -k --since "24 hours ago" | grep -o "rip-[a-z]*:" | sort | uniq -c

# 2. Is anything of yours in there? Check every source address
#    against your whitelist before you switch.
reportedip-agent whitelist list

# 3. Switch, and rebuild the rules.
sed -i "s/^mode: log/mode: drop/" /etc/reportedip-agent/config.yaml
reportedip-agent sync
reportedip-agent status

# 4. Only now the second switch, if you want it.
#    ban.enabled: true, then restart the daemon.
systemctl restart reportedip-agent.service
reportedip-agent ban list

Regarder ce qui est vraiment dans le noyau

reportedip-agent status est le résumé, et il lit à la fois les fichiers d'état et le noyau en direct afin que les deux puissent être comparés. Là où ils se contredisent, le noyau est la vérité, et status le dit : un enregistrement sans entrée dans le noyau est un bannissement qui n'a pas d'effet.

bash
# The agent's own view
reportedip-agent status
reportedip-agent ban list

# ipset backend, straight from the kernel
ipset list -t rip-ssh            # header and entry count only
ipset list rip-local             # entries, each with its timeout
iptables -S rip-blacklist
iptables -L INPUT -n --line-numbers | head

# nftables backend
nft list table inet reportedip
nft list set inet reportedip rip-local

Dans ban list, la colonne kernel est la durée qui reste encore dans le noyau et record ce qu'attend bans.json. Un tiret sous kernel à côté d'un enregistrement actif signifie que le bannissement n'a pas d'effet et que la synchronisation suivante le restaurera. Une ligne dont l'enregistrement dit none n'existe que dans le noyau : donc quelqu'un a utilisé ipset ou nft à la main, ou le registre a été perdu. Elle expirera quand même, mais aucun redémarrage ne la ramènera.

Lever un bannissement, et tout démonter

La sortie d'un enfermement est une seule commande. La règle de liste blanche est placée avant la règle de blocage, reportedip-agent whitelist add <address> agit donc immédiatement et passe au-dessus de chaque bannissement, y compris un bannissement déjà dans l'ensemble. Elle écrit le fichier et l'ensemble du noyau en une étape et ne demande ni synchronisation ni redémarrage.
bash
# Lift one ban and forget its history. The next detection starts
# from a first offence rather than escalating on top of a verdict
# you disagreed with.
reportedip-agent unban 203.0.113.45

# Never ban and never report this address or range, from now on.
reportedip-agent whitelist add 203.0.113.0/24 "customer office"

# Ban by hand. Works even with ban.enabled: false. A time given
# here is the time, not the first step of an escalation.
reportedip-agent ban add 203.0.113.45
reportedip-agent ban add 203.0.113.45 1440

# Stop blocking without uninstalling: no jump, the sets keep their entries.
sed -i "s/^mode: .*/mode: off/" /etc/reportedip-agent/config.yaml
reportedip-agent sync

# Remove the agent from the packet path completely (ipset backend).
iptables  -D INPUT -j rip-blacklist; iptables  -F rip-blacklist; iptables  -X rip-blacklist
ip6tables -D INPUT -j rip-blacklist; ip6tables -F rip-blacklist; ip6tables -X rip-blacklist
for s in $(ipset list -n | grep "^rip-"); do ipset destroy "$s"; done

# nftables backend
nft delete table inet reportedip

unban et whitelist add prennent tous deux le verrou de synchronisation : l'étape de restauration d'une synchronisation en cours ne peut donc pas remettre ce que vous êtes en train de lever. Retirer une entrée du fichier de liste blanche est la seule opération qui n'est pas immédiate : elle prend effet à la reconstruction de la synchronisation suivante, et retirer une exception n'a jamais besoin d'être instantané.

Ne laissez jamais un jeu de règles enregistré référencer un ensemble rip-. iptables-restore abandonne tout le fichier dès qu'il tombe sur un ensemble inconnu : une ligne oubliée dans /etc/iptables/rules.v4 peut donc vous enlever tout le pare-feu au prochain démarrage. L'agent reconstruit sa chaîne de lui-même à chaque démarrage et n'a besoin de rien d'enregistré. status avertit quand il trouve rip- dans rules.v4, rules.v6, /etc/sysconfig/iptables, ip6tables ou /etc/nftables.conf. Il ne regarde pas dans /etc/nftables.d.

Dernière mise à jour: · Maintenu par l’équipe ReportedIP

Security Focused
Conforme au RGPD
Made in Germany
Retour aux docs