
dns-honeypot
Como engenheiro que passa a maior parte dos dias imerso em ferramentas de observabilidade, tenho ocasionalmente uma ideia que simplesmente preciso colocar em prática. Este foi um desses experimentos: subir um resolvedor DNS em um IP limpo que ninguém anuncia, e depois deixar a internet falar com ele de qualquer forma. A única função do resolvedor era ficar quieto, registrar tudo e alimentar o Grafana com as consultas resultantes. Um docker compose up -d depois, eu tinha Unbound, Loki, Prometheus, Grafana e Traefik rastreando tráfego ao vivo e imprimindo histogramas de curiosidade, má configuração e o escaneador ocasional. Este README é o relatório desse primeiro dia, o que a pilha captura, por que isso é importante para mim e o que destaca sobre o cenário de segurança atual.
Introduzi intencionalmente zero sinal da minha parte, sem descarte de pacotes, sem respostas personalizadas, sem mitigação. Apenas Unbound com registro ativado, Loki monitorando o arquivo de log, Prometheus coletando métricas do exportador, Traefik na frente do Grafana e Docker Compose conectando tudo. O resolvedor estava em 94.130.27.226, um IPv4 “limpo” refrescante que eu havia encontrado (verifique seu status em https://www.abuseipdb.com/check/94.130.27.226 se quiser uma base pré-ruído), e deixei o mundo fazer o que queria. Um único laptop podia assistir a todos os painéis, executar tools/dns_query_storm.sh quando eu quisesse agitar as coisas, e depois deixar o ruído se acomodar nos padrões que a internet global escolhesse enviar.
Você pode dar uma olhada nesses painéis ao vivo em https://dns.cybersafeintl.co.uk/public-dashboards/eb554b5b74e14f4d95e376c0033ee83d, embora estejam no servidor mais básico da pilha, então espere atualizações lentas durante consultas pesadas.
unbound_total_num_queries do exportador do Unbound, então o painel “Throughput (QPS, 5m rate)” mostra consultas por segundo e detalha por origem. Essa visão responde à pergunta “quem está martelando o resolvedor?”, picos repentinos apontam diretamente para ASNs baseados em Bangladesh ou Polônia, e os logs facilitam ver se tempestades de SERVFAIL/NXDOMAIN acompanham as rajadas.client_ip, e os painéis já encapsulam tudo em topk(sort_desc(...)). Isso mantém os painéis limpos enquanto o script exportador me permite despejar as mesmas consultas em CSVs para análise offline, relatórios ou histórias reproduzíveis. A primeira captura mostrou cinco endereços IP nas faixas 45.179.* e 45.6.*, cada um disparando mais de 5k consultas em cinco minutos, seja uma fazenda de scanners ou um cliente agressivo.qname em janelas de 5m e 24h. O instantâneo de 5 minutos apresentou scb.se, dhl.com e cmu.edu, enquanto a exportação de 24h incluiu cbs.nl, scb.se, atlassian.com, e . Por que esses domínios? Essa é a parte interessante: são serviços legítimos, resolvedores mal configurados ou scanners oportunistas em busca de registros obsoletos? Mande uma nota se tiver uma teoria.Cada painel que você vê tem um CSV correspondente em exports/; empacote-os (zip -r exports.zip exports/) quando quiser anexar a história bruta a uma postagem de blog ou relatório de incidente.
docker-compose.yml sobe Unbound, o exportador do Unbound, Loki + Promtail, Prometheus, Grafana e Traefik com um único comando.unbound/ armazena configurações e logs do resolvedor. Controles de TTL, serve-expired e configurações de cache mantêm a fidelidade para capturarmos o que os clientes realmente pedem.prometheus/, loki/ e grafana/ contêm dados e arquivos de provisionamento para que métricas e painéis sobrevivam a reinicializações.grafana/dashboards/unbound-traffic-insights.json é pré-provisionado com a visão que você vê; todas as consultas PromQL/Loki já agregam e ordenam para manter os painéis legíveis.tools/dns_query_storm.sh permite simular tempestades de consultas quando você precisa testar tempos de reação.redeploy.sh automatiza a parada de toda a pilha, a atualização e a reconstrução com um único script.export_dashboard_data.py agora percorre o JSON do painel, executa cada consulta Prometheus/Loki e escreve arquivos CSV sanitizados em um diretório exports/ para compartilhamento.
cd hetzner_deploy/unbound-dnscp .env.example .env e configure GRAFANA_DOMAIN, credenciais de admin do Grafana, LETSENCRYPT_EMAIL e quaisquer substituições de TLS necessárias.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 (o exportador é Python puro).python export_dashboard_data.py --duration 24h --outdir exports/24h --timeout 90 para extrair todas as consultas do painel, converter para CSV e colocar os resultados em exports/24h.zip -r exports.zip exports/ para empacotar as tabelas brutas antes de publicá-las, anexá-las a uma postagem de blog ou enviá-las a colaboradores.--duration 6h ou timestamps --end para fatias direcionadas, ou use --filter domains se quiser apenas os painéis de domínio.Na exportação granular de 5 minutos, scb.se, dhl.com, cmu.edu, up.pt e utc.fr geraram centenas de milhares de consultas cada. Por que esses alvos? A constelação de domínios corporativos europeus me faz suspeitar de uma CDN, serviço de restauração ou scanner tentando reidratar caches obsoletos.
A exportação de 24 horas pinta um quadro ainda maior: cbs.nl, scb.se, atlassian.com, abb.com e up.pt geraram coletivamente mais de 250 milhões de consultas. Esse nível de volume não é ruído aleatório, são clientes de grande escala ou um appliance persistente que nunca para de resolver.
Os clientes mais ativos foram um punhado de endereços IPv4 45.179.* e 45.6.*, cada um disparando mais de 5k consultas nos cinco minutos observados. Eles podem fazer parte de um ISP ou fazenda de scanners, mas sejam o que forem, os painéis tornam trivial rastreá-los.
O que isso destaca? Ilustra como uma infraestrutura DNS exposta pode se tornar um feed passivo de tráfego interessante mesmo quando não é anunciada. A internet continua fazendo perguntas, e esta configuração simplesmente ouve com atenção. Se você está curioso sobre como este experimento se encaixa no meu trabalho mais amplo, confira os outros repositórios, às vezes eu coloco uma ideia dessas em prática e preciso ver aonde ela leva.
exports/ ou anexe os CSVs diretamente onde você conta a história.export_dashboard_data.py ou consultas Loki com metadados adicionais (ASN do cliente, motivo de SERVFAIL, país) para responder perguntas mais profundas.--duration 12h, --end ...), mantenha as saídas em diretórios com carimbo de data/hora e atualize este README com as estatísticas recentes para que a trama se mantenha atual.Se você está acompanhando com seu próprio honeypot, atualize este README com estatísticas de suas exportações para que possamos comparar histórias e ver se os mesmos sites e clientes continuam voltando.
Este projeto é fornecido “como está.” Não há garantias de qualquer tipo, expressas ou implícitas, incluindo, mas não se limitando a comercialização, adequação a um propósito específico ou não violação, e não sou responsável por quaisquer danos decorrentes de seu uso. Você assume todos os riscos associados à implantação, configuração ou operação desta pilha.
Se você achar este projeto útil, considere apoiá-lo:
| Moeda | Endereço |
|---|---|
| Bitcoin (BTC) | 3QjWqhQbHdHgWeYHTpmorP8Pe1wgDjJy54 |
| Ethereum (ETH) | 0x5851e6145F4773d1585b8686095FB16E368a4dA1 |
| ZCash (ZEC) | t1KSR5YkNPbjqRSCoLKo5AddFWdm9Kzxh1B |
abb.comup.pt