Aller au contenu principal

Guide d’intégration

Blocklist d’IP pour pare-feu Linux chargée dans des sets nftables par un timer systemd

curl télécharge la liste isMalicious complète avec votre clé API, lue dans un fichier netrc réservé à root. Un script charge les adresses dans des sets nftables avec des règles drop et les remplace en une seule transaction ; un timer systemd l’exécute toutes les heures.

Aucune carte bancaire requise · Clé API gratuite

Chemin des données
  1. isMalicious

    api.ismalicious.com

    blocklist-ips-critical.txt

    Régénérée toutes les 12 h

  2. Linux nftables

    Étape 3

    Installer le script de chargement

Sur cette page08

Ce que vous obtenez

Le script convertit la liste simple en sets nftables, que seule la mémoire du noyau limite. Choisissez une liste d’IP ; les listes de domaines sont pour les résolveurs DNS, pas pour ces sets.

ListeEntréesRégénéréeOffres
blocklist-ips-critical.txtPar défaut. IP signalées par 6 sources de menaces ou plus, ou par 3 ou plus avec une catégorie critique.environ 89 000toutes les 12 hBasic, Pro et Enterprise
blocklist-ips-critical50k.txtLes 50 000 IP de niveau critical au score de risque le plus élevé, pour un set plus petit.50 000, plafondtoutes les 12 hBasic, Pro et Enterprise
blocklist-ips-c2.txtIP de commande et contrôle (C2) signalées par des trackers de C2, quel que soit leur niveau.environ 44 000toutes les 12 hBasic, Pro et Enterprise

Nombres arrondis d’après la génération du  ; chaque liste est régénérée toutes les 12 heures. Les chiffres du jour sont publics et ne demandent aucune clé.

Ce que reçoit chaque offre

  • FreeCompte Free, ou aucune clé : les premiers 10 % de chaque liste, signalés par X-Blocklist-Version: lite.
  • Basic, Pro et EnterpriseBasic, Pro et Enterprise : toutes les listes, complètes.
  • Pro et EnterpriseCollections TAXII 2.1, pour les plateformes qui lisent les indicateurs STIX : Pro et Enterprise.

Comparer les offres

Ce que renvoie un téléchargementHTTP

GET https://api.ismalicious.com/blocklist/download/blocklist-ips-critical.txt

Liste complète ou échantillon de 10 %

ChampBasic, Pro et EnterpriseFree
X-Blocklist-Version:fulllite
X-Blocklist-Percentage:10010
Total entries:<COUNT><COUNT> (Lite Version - 10% of <TOTAL>)

Premières lignes du fichier

# IsMalicious.com Blocklist - IPs (Critical)
# Format: Plain
# Generated: <BUILD_TIME>
# Total entries: <COUNT>
# Update frequency: every 12 hours
# Category: All
# Threat level: Critical
# Website: https://ismalicious.com
# © <YEAR> IsMalicious (compilation). Licensed to the downloading account under https://ismalicious.com/terms; redistribution of the compilation prohibited. Third-party entries remain under their providers' licences — see https://ismalicious.com/sources.
#

Les valeurs entre chevrons sont fixées à chaque génération.

Prérequis

  • Un accès root, curl et nftables 1.0 ou ultérieur (la commande nft, testée avec la 1.0.6) installés depuis les paquets de votre distribution.
  • systemd 229 ou ultérieur, qui a introduit le RandomizedDelaySec du timer.
  • Une clé API et son secret isMalicious, dans Compte › Accès API.
  • Un accès HTTPS sortant (TCP 443) en IPv4 depuis l’hôte Linux vers api.ismalicious.com, qui n’a pas d’adresse IPv6.

Mise en place

  1. Copier la clé API et le secret

    Ouvrez Compte › Accès API et copiez la Clé API et le Secret API. La liste complète demande une offre Basic, Pro ou Enterprise ; avec une clé Free, le script reçoit l’échantillon de 10 % et le refuse.
  2. Stocker les identifiants dans un fichier netrc

    Créez /etc/ismalicious/netrc, réservé à root, avec les commandes ci-dessous, puis écrivez-y les trois lignes avec un éditeur : tapées dans un shell, elles finiraient dans son historique. curl y lit la clé et le secret : ils n’apparaissent jamais sur une ligne de commande ni dans la liste des processus.
    Créer le fichier, réservé à rootsh
    install -d -m 700 /etc/ismalicious
    [ -e /etc/ismalicious/netrc ] || install -m 600 /dev/null /etc/ismalicious/netrc
    chmod 600 /etc/ismalicious/netrc
    # Then write the three lines below into it with an editor, unless it holds them already.
    /etc/ismalicious/netrcnetrc
    machine api.ismalicious.com
    login <API_KEY>
    password <API_SECRET>
  3. Installer le script de chargement

    • Enregistrez le script sous /usr/local/sbin/ismalicious-sync, en mode 755, et placez vos adresses d’administration dans ALLOW4 : elles sont acceptées avant tout drop.
    • Il télécharge blocklist-ips-critical.txt, refuse un statut d’erreur, un contenu qui n’est pas une liste, l’échantillon de 10 % et un fichier dont le nombre d’entrées diffère de son en-tête, puis charge les adresses IPv4 et IPv6 dans deux sets de sa propre table, inet ismalicious, avec des règles drop en entrée, en transit et en sortie.
    • nft -c vérifie d’abord le fichier, et nft -f remplace la table en une seule transaction : en cas d’échec, la table précédente reste en place.
    • Pour charger une autre liste, changez le nom de fichier dans LIST.
    /usr/local/sbin/ismalicious-syncsh
    #!/bin/sh
    # Load the isMalicious IP list into nftables. The table is replaced in one
    # transaction; on any failure the previous one stays in place.
    set -eu
    NETRC=/etc/ismalicious/netrc
    LIST=blocklist-ips-critical.txt
    # IPv4 addresses this host must never drop, such as your management hosts:
    ALLOW4=""
    TMP=$(mktemp -d)
    trap 'rm -rf "$TMP"' EXIT
    
    # fetch_list LIST OUT: download one list to OUT and check it.
    # On any failure OUT is removed and the function returns 1.
    fetch_list() {
      if ! code=$(curl --silent --show-error --fail --netrc-file "$NETRC" \
          --proto '=https' --max-time 300 --retry 2 \
          --output "$2" --write-out '%{http_code}' "https://api.ismalicious.com/blocklist/download/$1"); then
        rm -f "$2"; echo "$1: download failed" >&2; return 1
      fi
      if [ "$code" != 200 ]; then
        rm -f "$2"; echo "$1: HTTP $code" >&2; return 1
      fi
      if ! head -n 1 "$2" | grep -q '^[#!] IsMalicious.com Blocklist'; then
        rm -f "$2"; echo "$1: not an isMalicious list" >&2; return 1
      fi
      if grep -q 'Lite Version' "$2"; then
        rm -f "$2"; echo "$1: lite list received, check the API key and the plan" >&2
        return 1
      fi
      # Every entry ends with a newline, and one header counts them: refuse a
      # cut, doubled or empty file.
      if [ -n "$(tail -c 1 "$2")" ]; then
        rm -f "$2"; echo "$1: cut short, no final newline" >&2; return 1
      fi
      if [ "$(grep -c '^[#!] Total entries:' "$2")" != 1 ]; then
        rm -f "$2"; echo "$1: not one Total entries line" >&2; return 1
      fi
      total=$(sed -n 's/^[#!] Total entries: \([0-9,]*\)$/\1/p' "$2" | tr -d ,)
      got=$(grep -c '^[^#!]' "$2" || true)
      if [ -z "$total" ] || [ "$total" = 0 ] || [ "$got" != "$total" ]; then
        rm -f "$2"; echo "$1: $got entries, the header says ${total:-none}" >&2
        return 1
      fi
    }
    
    fetch_list "$LIST" "$TMP/list.txt"
    
    OCTET='(25[0-5]|2[0-4][0-9]|1?[0-9]?[0-9])'
    grep -E "^($OCTET\.){3}$OCTET\$" "$TMP/list.txt" > "$TMP/v4" || true
    grep -E '^[0-9A-Fa-f:]*:[0-9A-Fa-f:]*$' "$TMP/list.txt" > "$TMP/v6" || true
    [ -s "$TMP/v4" ] || { echo "no IPv4 entries" >&2; exit 1; }
    for a in $ALLOW4; do echo "$a"; done > "$TMP/allow4"
    
    elements() {
      if [ -s "$1" ]; then
        printf '        elements = { %s }
    ' "$(paste -sd, "$1")"
      fi
    }
    
    cat > "$TMP/ismalicious.nft" <<NFT
    add table inet ismalicious
    delete table inet ismalicious
    table inet ismalicious {
        set allow4 {
            type ipv4_addr
            flags interval
    $(elements "$TMP/allow4")
        }
        set ism4 {
            type ipv4_addr
            flags interval
            auto-merge
    $(elements "$TMP/v4")
        }
        set ism6 {
            type ipv6_addr
            flags interval
            auto-merge
    $(elements "$TMP/v6")
        }
        chain input {
            type filter hook input priority -10; policy accept;
            ip saddr @allow4 accept
            ip saddr @ism4 drop
            ip6 saddr @ism6 drop
        }
        chain forward {
            type filter hook forward priority -10; policy accept;
            ip saddr @allow4 accept
            ip daddr @allow4 accept
            ip saddr @ism4 drop
            ip daddr @ism4 drop
            ip6 saddr @ism6 drop
            ip6 daddr @ism6 drop
        }
        chain output {
            type filter hook output priority -10; policy accept;
            ip daddr @allow4 accept
            ip daddr @ism4 drop
            ip6 daddr @ism6 drop
        }
    }
    NFT
    nft -c -f "$TMP/ismalicious.nft"
    nft -f "$TMP/ismalicious.nft"
    echo "loaded $(wc -l < "$TMP/v4") IPv4 and $(wc -l < "$TMP/v6") IPv6 entries"
  4. L’exécuter une première fois

    Exécutez le script en root. Il affiche le nombre d’entrées IPv4 et IPv6 chargées, ou la raison pour laquelle il a refusé la liste.
    Première exécutionsh
    /usr/local/sbin/ismalicious-sync
  5. La rafraîchir avec un timer systemd

    Enregistrez les unités service et timer sous /etc/systemd/system/, puis activez le timer. Il exécute le script après le démarrage, car la table ne survit pas à un redémarrage, puis toutes les heures ; RandomizedDelaySec retarde aussi l’exécution au démarrage, qui tombe entre 2 et 17 minutes après celui-ci.
    /etc/systemd/system/ismalicious-sync.servicesystemd
    [Unit]
    Description=Load the isMalicious IP blocklist
    Wants=network-online.target
    After=network-online.target
    
    [Service]
    Type=oneshot
    ExecStart=/usr/local/sbin/ismalicious-sync
    /etc/systemd/system/ismalicious-sync.timersystemd
    [Unit]
    Description=Refresh the isMalicious IP blocklist
    
    [Timer]
    OnBootSec=2min
    OnCalendar=hourly
    RandomizedDelaySec=15min
    Persistent=true
    
    [Install]
    WantedBy=timers.target
    Activer le timersh
    systemctl daemon-reload
    systemctl enable --now ismalicious-sync.timer

Vérifier le résultat

  • journalctl -u ismalicious-sync.service affiche loaded N IPv4 and M IPv6 entries après chaque exécution, ou la raison du refus de la liste.
  • systemctl list-timers ismalicious-sync.timer affiche la dernière et la prochaine exécution.
  • N plus M correspond au count de la liste dans /blocklist/stats, à une régénération près. nft list set peut afficher moins d’éléments : auto-merge fusionne les adresses contiguës en plages, et la couverture reste la même.
  • En root, la vérification d’en-tête affiche X-Blocklist-Version: full ; un autre utilisateur ne peut pas lire le fichier netrc, curl n’envoie alors aucune clé et la vérification affiche lite. Si root voit lite, voyez « lite list received » dans le dépannage.
Vérificationssh
# Next and last runs, and what the last run loaded:
systemctl list-timers ismalicious-sync.timer
journalctl -u ismalicious-sync.service

# The rules, then the first addresses of the IPv4 set:
nft list chain inet ismalicious input
nft list set inet ismalicious ism4 | head -n 20

# As root (the netrc file is root-only): full or lite.
sudo curl -sS -D - -o /dev/null --netrc-file /etc/ismalicious/netrc \
  https://api.ismalicious.com/blocklist/download/blocklist-ips-critical.txt

Dépannage

L’exécution affiche « download failed »

Un 401 signifie que la clé ou le secret du fichier netrc est faux ou incomplet : curl sort avec le code 22 et la table actuelle reste en place. Vérifiez le fichier : machine api.ismalicious.com, la clé en login, le secret en password, mode 600. Le corps de la réponse indique « Blocklist not found or empty » ; fiez-vous au code HTTP. Régénérer la clé dans Compte › Accès API invalide l’ancienne paire.

L’exécution affiche « lite list received »

Aucun identifiant n’est parvenu au serveur, à cause d’un mauvais chemin de netrc ou d’un mauvais nom de machine, ou l’offre est Free ou interrompue : un abonnement impayé, en retard de paiement, annulé, incomplet ou suspendu compte comme Free. La vérification d’en-tête décrite plus haut affiche alors X-Blocklist-Version: lite.

L’exécution affiche « entries, the header says », « cut short, no final newline » ou « not one Total entries line »

Le fichier était vide, tronqué ou n’était pas une des listes, comme quand un proxy ou un portail captif répond. La table actuelle reste en place ; l’exécution suivante réessaie.

Délais dépassés ou 502 sur une grande liste

Un téléchargement qui prend plus de 30 secondes de notre côté finit en délai dépassé ou en 502 : prenez une liste par niveau ou par catégorie du tableau.

« Message too long » renvoyé par nft

nft tourne dans un conteneur non privilégié, sans CAP_NET_ADMIN dans l’espace de noms initial, et ne peut pas agrandir son tampon de socket pour une liste de cette taille. Lancez le script sur l’hôte, ou dans un conteneur doté de cette capacité.

Erreurs de certificat

curl vérifie le certificat avec le magasin d’autorités du système : mettez à jour le paquet ca-certificates sur les systèmes anciens. N’ajoutez jamais --insecure : curl enverrait le secret à n’importe quel serveur qui répond.

403 ou 429 depuis ismalicious.com

Le frontal d’ismalicious.com refuse certaines sources. Utilisez api.ismalicious.com, comme le fait le script.

Limites

  • Ce guide ne publie que le script nftables. Un script pour ipset et iptables n’a pas encore été exécuté sur un hôte où ipset est installé : il n’est donc pas publié.
  • La table nftables ne survit pas seule à un redémarrage. Le timer la recharge entre 2 et 17 minutes après le démarrage ; d’ici là, l’hôte ne filtre pas sur cette liste.
  • Un redémarrage ou un rechargement de nftables.service, ou tout nft flush ruleset (le /etc/nftables.conf de Debian commence par un), supprime toutes les tables, celle-ci comprise, jusqu’à la prochaine exécution du timer. Lancez systemctl start ismalicious-sync.service après l’avoir rechargé.
  • Ni CIDR, ni plages, ni fichier nftables ou iptables-restore ne sont servis : le script construit les sets à partir de la liste simple.
  • L’échantillon de 10 % est le premier dixième d’un fichier non trié, pas le dixième le plus risqué.

Questions fréquentes

Existe-t-il une version du script pour ipset et iptables ?

Pas encore. Le script ipset que nous avons rédigé n’a pas été exécuté sur un hôte où ipset est installé : ce guide ne publie donc que le script nftables.

Pourquoi un fichier netrc plutôt que la clé sur la ligne de commande de curl ?

Le manuel de curl prévient que masquer une option dans la liste des processus ne suffit pas, et conseille de lire les données sensibles dans un fichier. Un fichier netrc réservé à root garde la clé et le secret hors de la liste des processus, de l’historique du shell et des crontabs.

À quelle fréquence recharger la liste ?

Toutes les heures, comme le fait le timer, et après chaque démarrage. Les listes sont régénérées toutes les 12 heures : une vérification horaire récupère chaque régénération peu après sa publication.

Le script bloque-t-il les adresses IPv6 ?

Oui. Une liste d’IP peut mêler adresses IPv4 et IPv6, et le script charge chaque famille dans son propre set, ism4 et ism6, chacun avec ses règles drop.

Fonctionne-t-il avec firewalld ou ufw ?

Avec firewalld et ufw, oui : ils ne réécrivent que leurs propres règles, et le script ajoute sa propre table nftables, inet ismalicious. Dans nftables, un paquet n’est accepté que si aucune règle ni politique de chaîne de base ne le rejette : le drop s’applique quoi que les autres tables acceptent. nftables.service est différent : un redémarrage, un rechargement ou tout nft flush ruleset supprime toutes les tables, celle-ci comprise, jusqu’à la prochaine exécution du timer.

Commencer

Prêt à commencer ?

Aucune carte bancaire requise · Clé API gratuite