
dns-honeypot
En tant qu’ingénieur qui passe la plupart de ses journées plongé dans les outils d’observabilité, j’ai parfois une idée que je dois simplement suivre. C’était l’une de ces expériences : lancer un résolveur DNS sur une IP propre que personne n’annonce, puis laisser Internet lui parler quand même. Le seul travail du résolveur était de rester silencieux, de tout journaliser et d’alimenter Grafana avec les requêtes résultantes. Un docker compose up -d plus tard, j’avais Unbound, Loki, Prometheus, Grafana et Traefik qui suivaient le trafic en direct et imprimaient des histogrammes de curiosité, de mauvaise configuration et du scanner occasionnel. Ce README est le rapport de ce premier jour, ce que la pile capture, pourquoi c’est important pour moi et ce que cela met en lumière sur le paysage actuel de la sécurité.
J’ai intentionnellement introduit zéro signal de mon côté, pas de perte de paquets, pas de réponses adaptées, pas d’atténuation. Juste Unbound avec la journalisation activée, Loki qui suit le fichier de logs, Prometheus qui scrape les métriques de l’exportateur, Traefik qui sert de frontend à Grafana et Docker Compose qui les relie. Le résolveur se trouvait sur 94.130.27.226, une IPv4 rafraîchissante « propre » que j’avais trouvée (vérifiez son état sur https://www.abuseipdb.com/check/94.130.27.226 si vous voulez une base pré-bruit), et j’ai laissé le monde faire son affaire. Un seul ordinateur portable pouvait regarder chaque panneau, lancer tools/dns_query_storm.sh quand je voulais remuer la marmite, puis laisser le bruit retomber dans les schémas que l’Internet global choisissait d’envoyer.
Vous pouvez jeter un œil à ces tableaux de bord en direct sur https://dns.cybersafeintl.co.uk/public-dashboards/eb554b5b74e14f4d95e376c0033ee83d, bien qu’ils soient hébergés sur le serveur le plus bas de gamme de la pile, attendez-vous donc à des rafraîchissements lents pendant les requêtes lourdes.
unbound_total_num_queries de l’exportateur Unbound, donc le panneau « Throughput (QPS, 5m rate) » montre les requêtes par seconde et les décompose par source. Cette vue répond à la question « qui martèle le résolveur ? », les pics soudains pointent directement vers des ASN basés au Bangladesh ou en Pologne, et les logs permettent de voir facilement si des tempêtes de SERVFAIL/NXDOMAIN accompagnent les rafales.client_ip, et les tableaux de bord intègrent déjà topk(sort_desc(...)). Cela garde les panneaux propres tandis que le script d’exportation me permet de vider les mêmes requêtes dans des CSV pour une analyse hors ligne, des rapports ou des histoires reproductibles. La première capture a montré cinq adresses IP dans les plages 45.179.* et 45.6.*, chacune émettant plus de 5k requêtes en cinq minutes, soit une ferme de scanners, soit un client agressif.qname sur des fenêtres de 5 min et 24 h. L’instantané de 5 minutes incluait scb.se, dhl.com et cmu.edu, tandis que l’exportation de 24 h incluait cbs.nl, scb.se, atlassian.com, et . Pourquoi ces domaines ? C’est la partie intéressante, s’agit-il de services légitimes, de résolveurs mal configurés ou de scanners opportunistes à la recherche d’enregistrements obsolètes ? Envoyez-moi un mot si vous avez une théorie.Chaque panneau que vous voyez a un CSV correspondant dans exports/ ; regroupez-les (zip -r exports.zip exports/) quand vous voulez joindre l’histoire brute à un article de blog ou à un rapport d’incident.
docker-compose.yml démarre Unbound, l’exportateur Unbound, Loki + Promtail, Prometheus, Grafana et Traefik en une seule commande.unbound/ stocke les configurations du résolveur et les logs. Les contrôles TTL, serve-expired et les paramètres de cache maintiennent la fidélité afin que nous capturions ce que les clients demandent réellement.prometheus/, loki/ et grafana/ contiennent les données et les fichiers de provisionnement afin que les métriques et les tableaux de bord survivent aux redémarrages.grafana/dashboards/unbound-traffic-insights.json est pré-provisionné avec la vue que vous voyez ; toutes les requêtes PromQL/Loki agrègent et trient déjà pour garder les panneaux lisibles.tools/dns_query_storm.sh vous permet de simuler des tempêtes de requêtes lorsque vous devez tester les temps de réaction.redeploy.sh automatise la mise hors service de toute la pile, la récupération des mises à jour et la reconstruction avec un seul script.export_dashboard_data.py parcourt maintenant le JSON du tableau de bord, frappe chaque requête Prometheus/Loki et écrit des fichiers CSV nettoyés dans un répertoire pour les partager.
cd hetzner_deploy/unbound-dnscp .env.example .env et configurez GRAFANA_DOMAIN, les identifiants administrateur Grafana, LETSENCRYPT_EMAIL et toutes les surcharges TLS nécessaires.sudo chown -R 472:472 grafana-data && sudo mkdir -p prometheus/data && sudo chown -R 65534:65534 prometheus/datadocker compose build && docker compose up -dpip install requests (l’exportateur est en Python pur).python export_dashboard_data.py --duration 24h --outdir exports/24h --timeout 90 pour récupérer chaque requête du tableau de bord, la convertir en CSV et placer les résultats dans exports/24h.zip -r exports.zip exports/ pour regrouper les tables brutes avant de les publier, de les joindre à un article de blog ou de les envoyer à des collaborateurs.--duration 6h ou des horodatages --end pour des tranches ciblées, ou utilisez --filter domains si vous ne voulez que les panneaux de domaines.scb.se, dhl.com, cmu.edu, up.pt et utc.fr ont chacun généré des centaines de milliers de requêtes. Pourquoi ces cibles ? La constellation de domaines d’entreprises européennes me fait soupçonner un CDN, un service de restauration ou un scanner qui tente de réhydrater des caches obsolètes.cbs.nl, scb.se, atlassian.com, abb.com et up.pt ont collectivement généré plus de 250 millions de requêtes. Ce niveau de volume n’est pas un bruit aléatoire, soit des clients à grande échelle, soit un appareil persistant qui ne cesse jamais de résoudre.45.179.* et 45.6.*, chacune dépassant 5k requêtes dans les cinq minutes observées. Ils font peut-être partie d’un FAI ou d’une ferme de scanners, mais quoi qu’ils soient, les tableaux de bord les rendent faciles à suivre.Qu’est-ce que cela met en évidence ? Cela illustre à quel point une infrastructure DNS exposée peut devenir un flux passif de trafic intéressant, même lorsqu’elle n’est pas annoncée. Internet continue de poser des questions, et cette configuration se contente d’écouter attentivement. Si vous êtes curieux de savoir comment cette expérience s’inscrit dans mon travail plus large, consultez les autres dépôts, parfois je lance une idée comme celle-ci et je dois voir où elle mène.
exports/ ou joignez directement les CSV là où vous racontez l’histoire.export_dashboard_data.py ou les requêtes Loki avec des métadonnées supplémentaires (ASN client, raison SERVFAIL, pays) pour répondre à des questions plus approfondies.--duration 12h, --end ...), conservez les sorties dans des répertoires horodatés et mettez à jour ce README avec les statistiques fraîches pour que l’intrigue reste actuelle.Si vous suivez avec votre propre honeypot, mettez à jour ce README avec les statistiques de vos exportations afin que nous puissions comparer les histoires et voir si les mêmes sites et clients reviennent sans cesse.
Ce projet est fourni « en l’état ». Il n’y a aucune garantie d’aucune sorte, expresse ou implicite, y compris mais sans s’y limiter la qualité marchande, l’adéquation à un usage particulier ou l’absence de contrefaçon, et je ne suis pas responsable des dommages résultant de son utilisation. Vous assumez tous les risques associés au déploiement, à la configuration ou à l’exploitation de cette pile.
Si vous trouvez ce projet utile, pensez à le soutenir :
| Devise | Adresse |
|---|---|
| Bitcoin (BTC) | 3QjWqhQbHdHgWeYHTpmorP8Pe1wgDjJy54 |
| Ethereum (ETH) | 0x5851e6145F4773d1585b8686095FB16E368a4dA1 |
| ZCash (ZEC) | t1KSR5YkNPbjqRSCoLKo5AddFWdm9Kzxh1B |
abb.comup.ptexports/