
dns-honeypot
Как инженер, который большую часть времени проводит, погрузившись в инструменты наблюдаемости, я иногда получаю идеи, которые просто обязан воплотить. Это был один из таких экспериментов: запустить DNS-резолвер на чистом IP, который никто не рекламирует, и позволить интернету общаться с ним, как получится. Единственной задачей резолвера было молчать, логировать всё и передавать результаты запросов в Grafana. Один docker compose up -d — и у меня были Unbound, Loki, Prometheus, Grafana и Traefik, отслеживающие трафик в реальном времени и печатающие гистограммы любопытства, неправильных конфигураций и случайных сканеров. Этот README — отчёт о первом дне: что захватывает стек, почему это важно для меня и что он подчёркивает в текущем ландшафте безопасности.
Я намеренно не вносил никаких сигналов со своей стороны — ни сброса пакетов, ни кастомных ответов, ни блокировок. Просто Unbound с включённым логированием, Loki, следящий за файлом лога, Prometheus, собирающий метрики экспортёра, Traefik, стоящий перед Grafana, и Docker Compose, связывающий всё вместе. Резолвер находился на 94.130.27.226 — освежающе «чистом» IPv4, который я нашёл (проверьте его статус на https://www.abuseipdb.com/check/94.130.27.226, если хотите увидеть базовый уровень шума), и я позволил миру делать своё дело. Один ноутбук мог смотреть на все панели, запускать tools/dns_query_storm.sh, когда хотелось взболтать смесь, а затем давать шуму улечься обратно в те паттерны, которые глобальный интернет решал прислать.
Вы можете заглянуть на эти дашборды вживую по адресу https://dns.cybersafeintl.co.uk/public-dashboards/eb554b5b74e14f4d95e376c0033ee83d, хотя они работают на самом дешёвом сервере в стеке, так что ожидайте медленных обновлений при тяжёлых запросах.
unbound_total_num_queries экспортёра Unbound, так что панель «Throughput (QPS, 5m rate)» показывает запросы в секунду и разбивает их по источнику. Этот взгляд отвечает на вопрос «кто долбит резолвер?» — внезапные пики прямо указывают на ASN из Бангладеш или Польши, а логи позволяют легко увидеть, сопровождаются ли всплески шквалом SERVFAIL/NXDOMAIN.client_ip, а дашборды уже оборачивают всё в topk(sort_desc(...)). Это сохраняет панели чистыми, а скрипт экспорта позволяет выгружать те же запросы в CSV для офлайн-анализа, отчётности или воспроизводимых историй. Первый захват показал пять IP-адресов в диапазонах 45.179.* и 45.6.*, каждый из которых отправлял более 5 000 запросов за пять минут — либо ферма сканеров, либо агрессивный клиент.qname за окна в 5 минут и 24 часа. Пятиминутный срез содержал scb.se, dhl.com и cmu.edu, а 24-часовая выгрузка включала cbs.nl, scb.se, atlassian.com, abb.com и . Почему эти домены? Это и есть интересная часть — легитимные ли это сервисы, неправильно настроенные резолверы или оппортунистические сканеры, охотящиеся за устаревшими записями? Сообщите мне, если у вас есть теория.Каждая панель, которую вы видите, имеет соответствующий CSV в exports/; упакуйте их (zip -r exports.zip exports/), когда захотите прикрепить сырую историю к посту в блоге или отчёту об инциденте.
docker-compose.yml поднимает Unbound, экспортёр Unbound, Loki + Promtail, Prometheus, Grafana и Traefik одной командой.unbound/ хранит конфиги и логи резолвера. Контроль TTL, serve-expired и настройки кеша обеспечивают достоверность, чтобы мы захватывали именно то, что спрашивают клиенты.prometheus/, loki/ и grafana/ содержат данные и файлы провижининга, чтобы метрики и дашборды переживали перезапуски.grafana/dashboards/unbound-traffic-insights.json предварительно подготовлен с тем видом, который вы видите; все запросы PromQL/Loki уже агрегированы и отсортированы для читаемости панелей.tools/dns_query_storm.sh позволяет имитировать шквалы запросов, когда нужно протестировать время реакции.redeploy.sh автоматизирует снос всего стека, подтягивание обновлений и пересборку одним скриптом.export_dashboard_data.py теперь обходит JSON дашборда, выполняет каждый запрос Prometheus/Loki и записывает очищенные CSV-файлы в каталог exports/ для обмена.
cd hetzner_deploy/unbound-dnscp .env.example .env и настройте GRAFANA_DOMAIN, учётные данные администратора Grafana, LETSENCRYPT_EMAIL и любые необходимые переопределения TLS.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 (экспортёр написан на чистом Python).python export_dashboard_data.py --duration 24h --outdir exports/24h --timeout 90 — чтобы вытянуть все запросы дашборда, преобразовать их в CSV и поместить результаты в exports/24h.zip -r exports.zip exports/ — чтобы упаковать сырые таблицы перед публикацией, прикреплением к посту в блоге или отправкой соавторам.--duration 6h или временными метками --end для целевых срезов, или используйте --filter domains, если вам нужны только панели с доменами.scb.se, dhl.com, cmu.edu, up.pt и utc.fr генерировали сотни тысяч запросов каждый. Почему именно эти цели? Созвездие европейских корпоративных доменов наводит на мысль о CDN, сервисе восстановления или сканере, пытающемся «реанимировать» устаревшие кеши.cbs.nl, scb.se, atlassian.com, abb.com и up.pt совместно сгенерировали более 250 миллионов запросов. Такой объём — не случайный шум: либо крупномасштабные клиенты, либо настойчивое устройство, которое никогда не прекращает резолвинг.45.179.* и 45.6.*, каждый из которых выпустил более 5 000 запросов за наблюдаемые пять минут. Возможно, они часть ISP или фермы сканеров, но кем бы они ни были, дашборды делают отслеживание тривиальным.Что это подчёркивает? Это иллюстрирует, как открытая DNS-инфраструктура может стать пассивным источником интересного трафика, даже если её не рекламируют. Интернет продолжает задавать вопросы, а эта установка просто внимательно слушает. Если вам интересно, как этот эксперимент вписывается в мою более широкую работу, загляните в другие репозитории — иногда я запускаю такую идею и просто смотрю, куда она приведёт.
exports/ или прикрепите CSV напрямую туда, где рассказываете историю.export_dashboard_data.py или запросы Loki дополнительными метаданными (ASN клиента, причина SERVFAIL, страна), чтобы отвечать на более глубокие вопросы.--duration 12h, --end ...), сохраняйте результаты в каталоги с временными метками и обновляйте этот README свежей статистикой, чтобы сюжет оставался актуальным.Если вы тоже следите за своей приманкой, обновите этот README статистикой из ваших экспортов, чтобы мы могли сравнить истории и увидеть, возвращаются ли те же сайты и клиенты.
Этот проект предоставляется «как есть». Никаких гарантий любого рода, явных или подразумеваемых, включая, но не ограничиваясь, гарантиями товарной пригодности, пригодности для определённой цели или ненарушения прав, не предоставляется, и я не несу ответственности за любой ущерб, возникший в результате его использования. Вы принимаете все риски, связанные с развёртыванием, настройкой или эксплуатацией этого стека.
Если вы нашли этот проект полезным, рассмотрите возможность поддержки:
| Валюта | Адрес |
|---|---|
| Bitcoin (BTC) | 3QjWqhQbHdHgWeYHTpmorP8Pe1wgDjJy54 |
| Ethereum (ETH) | 0x5851e6145F4773d1585b8686095FB16E368a4dA1 |
| ZCash (ZEC) | t1KSR5YkNPbjqRSCoLKo5AddFWdm9Kzxh1B |
up.pt