Criei meu próprio resolvedor DNS em Go em vez de usar o Unbound: Eis o porquê e o que aprendi

Criei meu próprio resolvedor DNS em Go em vez de usar o Unbound: Eis o porquê e o que aprendi

O autor relata a experiência de construir um resolvedor DNS recursivo em Go para um projeto similar ao NextDNS, abordando os desafios e as razões para não utilizar soluções prontas como o Unbound. Ele detalha os problemas enfrentados, as otimizações implementadas e os resultados alcançados, além de compartilhar o código open-source.

MundiX News·15 de maio de 2026·10 min de leitura·👁 19 views

Olá, Habr!

Há três meses, comecei a criar um clone do NextDNS para a Europa: um DNS recursivo com filtragem de anúncios, rastreadores e malware. No primeiro dia, abri o Unbound, li o manual e tudo pareceu claro. À noite, percebi que não era adequado. Uma semana depois, estava escrevendo meu próprio resolvedor em Go e me lembrei do ditado sobre a pessoa que decidiu escrever um servidor de e-mail. Aconteceu de novo.

Atualmente, em produção: 10 nós ao redor do mundo, respondendo a DoH/DoT, filtrando milhões de domínios, com 60 MB de RAM por nó. Vou explicar por que abandonei as soluções prontas, quais foram os pontos problemáticos e onde o Unbound ainda é mais rápido. Spoiler: quase em todos os lugares, mas em nossas condições isso não importa. No final, há links para o núcleo open-source do resolvedor e nossa tarifa gratuita, para você experimentar.

Por que criar seu próprio resolvedor se existe o Unbound?

Unbound é um excelente software. PowerDNS Recursor também. Eu os adoro como se adora um gato velho: pelo simples fato de existirem e não exigirem explicações. Em uma situação normal, eu simplesmente instalaria um deles e iria tomar um chá. Mas eu tinha três requisitos que nenhum dos dois atendia de forma nativa:

Milhões de endpoints DoH com diferentes regras de filtragem

Em um produto similar ao NextDNS, cada usuário recebe seu próprio config_id, um token público curto na URL:

https://dns.vantagedns.com/<config_id>/dns-query

Um usuário pode ter perfis "casa", "crianças", "escritório", cada um com suas próprias blocklists e whitelists. Não é "um resolvedor com uma configuração", mas dezenas de milhares de resolvedores lógicos em um único nó.

O Unbound tem views, mas eles não escalam para dezenas de milhares de conjuntos de regras independentes sem dor de cabeça com a geração de configuração e SIGHUP a cada cinco minutos. Eu vi uma construção semelhante em uma empresa de telecomunicações em 2014. Lá, o administrador carregava um pedaço de papel com a ordem das ações para não esquecer. Eu não queria me envolver nisso.

Query log in-memory sem gravar no disco

O nó de borda não deve gravar nada no disco que se refira ao usuário. Isso faz parte do posicionamento. Portanto, o query log reside em um buffer circular na memória, enviado de forma assíncrona para o ClickHouse em Helsinque, e só. O Unbound grava logs em um arquivo; para o envio assíncrono, é preciso construir um tail+parser.

Retention: 24 horas no plano gratuito, até 30 dias nos planos pagos, depois o ClickHouse TTL limpa.

Filtros de Bloom para blocklists com compartilhamento entre perfis

Temos mais de 10 blocklists, de 50K a 5M de domínios cada. Se armazená-los por perfil como sets, seriam centenas de MB de RAM por nó. Com Bloom: 8 MB por lista, compartilhado entre todos os perfis, com uma taxa de falsos positivos < 0,1%. O Unbound não tem isso; há local-zone (lento para listas grandes) ou RPZ (também não é exatamente o que eu queria).

Considerei por muito tempo as opções de "customizar o Unbound através de módulos" e desisti. A API de módulos em C, milhões de configurações através de um socket Unix, é um caminho para o inferno do debugging, e logo no quinto círculo. Eu não tenho nervos nem vida para isso.

Por que Go, e não Rust/C++?

Resposta curta: eu conheço Go e não conheço Rust no nível de "escrever um programa de sistema de rede sob carga". E a última vez que escrevi em C foi na universidade, quando ainda pensava que um segfault era um problema de diagnóstico interessante. Agora eu sei que é apenas uma punição pela arrogância.

Resposta longa:

CritérioGoRustC/C++
Velocidade de start✅ < 1 s✅ < 1 s✅ < 1 s
Memory safety✅ GC✅ borrow check
Tempo até protótipo✅ dias⚠️ semanas❌ meses
Library: DNSmiekg/dns (padrão de fato)⚠️ trust-dns ok, mas mais pobre✅ muitos
Gorout./async✅ goroutine por requisição - normal⚠️ async runtime❌ epoll na mão

miekg/dns resolveu 80% das tarefas prontas para uso: parsing de wire-format, serialização, EDNS, DNSSEC. Eu escrevi sobre ele recursive resolution, cache, filtragem.

Com Rust, eu ganharia 10-15% em latência e alguns MB em RAM. Mas perderia 2 meses reescrevendo. Para um projeto bootstrap de 1 pessoa, isso não é vantajoso.

O que foi doloroso

A recursive resolution não é apenas "perguntar ao .com NS, depois ao NS da zona"

Quando você escreve um recursive resolver pela primeira vez, parece: bem, vamos recursivamente aos NS, armazenamos em cache, tudo certo. Qualquer calouro escreverá em uma noite. A realidade, como sempre, me bateu com um porrete na cabeça e me chamou de ingênuo.

  • NS lookups paralelos. Uma zona geralmente tem 2-4 NS autoritativos. Se você chamar cada um sequencialmente em um timeout, em um cache frio, um resolve de example.com pode levar mais de 5 segundos. Goroutines paralelas, race-to-first-response, eliminação de lentos.
  • Glue records. Quando você solicita ns1.example.com para a zona example.com, é um problema do ovo e da galinha. O servidor autoritativo retorna um registro A para o NS diretamente na seção additional. Se você ignorá-lo, a recursão entra em loop. Houve um bug em que o resolvedor travava em um loop porque ignorava o additional.
  • Negative caching. RFC 2308 (1998, aliás, saudações da era em que o DNS ainda era considerado simples). Se o NS retornou NXDOMAIN, você deve armazenar em cache com o TTL do SOA, e não da resposta. Caso contrário, no primeiro timeout, armazenamos em cache "o domínio não existe" por uma hora padrão e o usuário reclama, e eu olho para os logs e não entendo por que o GitHub está fora do ar só para mim.
  • QNAME minimisation. Deve ser ativado por padrão, é privacidade. Você solicita mail.google.com → para . você pergunta apenas com, para com apenas google.com, para google.com já o mail.google.com completo. Não "mostramos o qname completo para todos os NS no caminho". Implementar com cuidado é uma história separada: alguns NS ruins respondem NODATA a uma solicitação minimizada, e você fica sentado, pegando-os nos logs.
  • EDNS Client Subnet — um inferno à parte. Sem ECS, o Google retorna o IP do CDN do país onde seu nó está localizado. Um usuário em Berlim através do nosso nó em Helsinque recebe um IP finlandês para googlevideo.com. Ping de 80 ms em vez de 5 ms. O YouTube fica lento, o usuário escreve que "tudo está quebrado" para nós.

Com o ECS, você publica a sub-rede /24 do usuário para o NS autoritativo. E aqui começa. Parte do NS cospe no ECS. O Cloudflare não usa por princípio, porque é anycast. Parte retorna o IP "correto". Parte retorna o IP incorreto, e então você passa uma semana descobrindo o porquê. RFC 7871 é formalmente opcional, e cada servidor interpreta "opcional" à sua maneira, como ex-cônjuges interpretam "vamos continuar amigos".

Testar em mais de 30 domínios manualmente foi a etapa mais tediosa em todos os três meses.

DNSSEC validation

Implementar uma validation chain do zero leva duas semanas de tempo puro. No final, eu o ativei opcionalmente: para a maioria dos usuários, agora é principalmente cosmético (95% dos domínios ainda estão sem assinatura), e a baggage é séria.

Cache poisoning — paranoia 24/7

Qualquer resolvedor de cache é um alvo potencial para cache poisoning. Source port randomization, txn-id randomization, 0x20 case randomization (sim, aquele truque com a capitalização das letras no qname, que parece um remendo e é), não confiar na seção additional sem confirmação através do bailiwick. Tudo isso deve ser feito antes do lançamento, não depois.

Reescrevi a validação da resposta umas 5 vezes. Cada vez encontrava um novo edge case e pensava "agora está tudo certo". Não é assim que funciona. Lembrem-se disso, crianças.

Números: o que aconteceu no final

Métricas de um nó (Hetzner CPX21, 3 vCPU, 4 GB RAM, Helsinque):

QPS sustained:           ~12 000 cached / ~3 500 cold
P50 latency cached:      0.3 ms
P50 latency cold (.com): 38 ms
P99 latency cold:        180 ms
RAM steady state:        62 MB
Binary size:             14 MB (go build -ldflags="-s -w")
Cold start to ready:     0.4 s

Para comparação, Unbound no mesmo nó com uma configuração semelhante:

QPS sustained:           ~18 000 cached / ~5 000 cold
P50 latency cached:      0.18 ms
RAM steady state:        85 MB

O Unbound é 30-40% mais rápido em cached lookups. Isso é esperado: ele é em C, o código foi aprimorado por 20 anos. Em solicitações frias, a diferença é menor, porque estamos limitados pela rede.

Para nossa carga (~500 QPS por nó no pico na fase atual), essa diferença não existe.

O que eu faria de diferente

Eu teria ativado o pprof e o continuous profiling desde o primeiro dia. Nos primeiros dois meses, depurei as alocações através de runtime.ReadMemStats e top como um homem das cavernas. Com pprof + Parca, eu encontraria vazamentos em minutos, não em noites. Em minha defesa, direi que às três da manhã parece que top é uma ferramenta normal.

Eu não escreveria Bloom filters imediatamente, eu pegaria suffix trees. Bloom é necessário na escala de milhões de domínios. No início, eu tinha 200K registros na lista, um suffix-trie normal daria exact matching sem falsos positivos, mais fácil de depurar. Eu adicionaria Bloom mais tarde, quando já estivesse apertando. Esta, aliás, é a regra principal: não otimize o que não está quebrado. Eu o conheço desde 2010 e o quebro regularmente.

Eu teria feito feature flags desde o primeiro dia. Agora eu tenho 4 caminhos diferentes no código "se o ECS estiver ativado - assim, caso contrário, assim", e eles estão entrelaçados como os cabos atrás da mesa de qualquer administrador antigo. Com flags, seria possível testar em produção em 1% do tráfego. Sem eles, eu testo em mim mesmo, o que é bastante humilhante.

Open-source

O Edge-resolver é open source, MIT. Link no final do artigo. O que NÃO é open-source: control plane (billing, dashboard, blocklist-catalog) - isso é negócio.

Por que open-source edge: eu quero que o usuário possa levantar sua própria instância e certificar-se de que não estamos mentindo sobre "não escrever no disco". No transparency report - estatísticas de solicitações para policiais. Warrant canary atualizamos semanalmente.

O que vem a seguir

Nos próximos posts, pretendo analisar os detalhes:

  • como fiz Bloom filters com compartilhamento entre perfis;
  • por que abandonei o anycast em favor do geo-DNS em 10 PoPs e quanto isso realmente custa;
  • como enviamos o query log de forma assíncrona para o ClickHouse sem perdas e sem disco na edge.

Se você estiver interessado em algo específico - escreva nos comentários, tentarei priorizar.

Links:

Obrigado por ler até o fim. Comentários e perguntas escreva nos comentários.

🛡️⚡

Pare de pesquisar. Comece a hackear.

O MundiX é seu copiloto de pentest com IA: comandos exatos, análise de outputs e próximo passo na kill chain — em segundos.

Testar grátis por 7 dias →

Sem cartão para começar · Planos a partir de R$49/mês

📤 Compartilhar & Baixar

🧰 Ferramentas recomendadas

Divulgação: alguns links são patrocinados. Podemos receber comissão se você comprar — sem custo extra para você. Só indicamos o que faz sentido para a comunidade.

Aprendendo Kali Linux: Teste de segurança, pentest e hacking ético

Aprendendo Kali Linux: Teste de segurança, pentest e hacking ético

Com centenas de ferramentas pré-instaladas, a distribuição Kali Linux facilita o trabalho de os profissionais de segurança começarem a fazer testes de segurança rapidamente. No entanto, com mais de 600 ferramentas em seu arsenal, o Kali Linux também pode ser desafiador. A nova edição deste prático livro abrange as atualizações nas ferramentas e inclui uma melhor abordagem da análise forense e da engenharia reversa. Ric Messier, autor, não fica apenas no teste de segurança, mas também faz uma abordagem sobre a execução de análise forense, incluindo a análise em disco e na memória, assim como alguma análise básica de malware. • Explore as diversas ferramentas disponíveis no Kali Linux • Entenda o valor do teste de segurança e examine os tipos de teste disponíveis • Aprenda os aspectos básicos do pentest em todo o ciclo de vida do ataque • Instale o Kali Linux em vários sistemas, tanto físicos quanto virtuais • Descubra como usar diferentes ferramentas destinadas à segurança • Estruture um teste de segurança baseado nas ferramentas do Kali Linux • Estenda as ferramentas do Kali para criar técnicas de ataque avançadas • Use o Kali Linux para ajudar a criar relatórios quando o teste terminar “A abordagem concisa, clara e baseada na experiência adotada por Ric Messier para a introdução do Kali Linux e dos testes de cibersegurança é incomparável. Este livro é uma leitura excelente e acessível para iniciantes e um recurso valioso para qualquer pessoa.” —Alexander Arlt, Consultor sênior de segurança, Google

Ver na Amazon
Gshield 2 em 1 Hub Extensor Conector USB-C + USB-A e Adaptador de Rede Ethernet LAN RJ45 com 3 Entradas USB 3.0 até 5 Gbps em Liga de Alumínio para Computador e Notebook, Cinza

Gshield 2 em 1 Hub Extensor Conector USB-C + USB-A e Adaptador de Rede Ethernet LAN RJ45 com 3 Entradas USB 3.0 até 5 Gbps em Liga de Alumínio para Computador e Notebook, Cinza

Compatível com portas USB-C e USB-A, ideal para ampliar a conectividade de dispositivos como MacBook Pro e outros com portas USB-C. Inclui um adaptador USB-A extra, proporcionando uma conexão Ethernet estável e veloz de até 1 Gbps, perfeita para filmes, jogos online e videoconferências. Oferece três portas USB 3.0 com velocidades de transferência de até 5 Gbps, permitindo conectar mouse, teclado, discos rígidos e outros periféricos. Fabricado em alumínio durável, garantindo longa vida útil e resistência ao uso diário. Design compacto e leve, ideal para viagens de negócios e uso diário, facilitando o transporte e armazenamento. Funciona com Windows 10/8.1/8, Mac OS e Chrome OS, oferecendo versatilidade incomparável para diversas necessidades de conectividade. Assegura uma conectividade estável e rápida, perfeita para tarefas exigentes como transferência de dados, streaming e mais.

Ver na Amazon
Hacking APIs: Breaking Web Application Programming Interfaces

Hacking APIs: Breaking Web Application Programming Interfaces

Hacking APIs is a crash course on web API security testing that will prepare you to penetration-test APIs, reap high rewards on bug bounty programs, and make your own APIs more secure. You'll learn how REST and GraphQL APIs work in the wild and set up a streamlined API testing lab with Burp Suite and Postman. Then you'll master tools useful for reconnaissance, endpoint analysis, and fuzzing, such as Kiterunner and OWASP Amass. Next, you'll learn to perform common attacks, like those targeting an API's authentication mechanisms and the injection vulnerabilities commonly found in web applications. You'll also learn techniques for bypassing protections against these attacks. In the book's nine guided labs, which target intentionally vulnerable APIs, you'll practice: Enumerating APIs users and endpoints using fuzzing techniques Using Postman to discover an excessive data exposure vulnerability Performing a JSON Web Token attack against an API authentication process Combining multiple API attack techniques to perform a NoSQL injection Attacking a GraphQL API to uncover a broken object level authorization vulnerability

Ver oferta
Gray Hat Hacking: The Ethical Hacker's Handbook, Sixth Edition

Gray Hat Hacking: The Ethical Hacker's Handbook, Sixth Edition

Up-to-date strategies for thwarting the latest, most insidious network attacks This fully updated, industry-standard security resource shows, step by step, how to fortify computer networks by learning and applying effective ethical hacking techniques. Based on curricula developed by the authors at major security conferences and colleges, the book features actionable planning and analysis methods as well as practical steps for identifying and combating both targeted and opportunistic attacks. Gray Hat Hacking: The Ethical Hacker's Handbook, Sixth Edition clearly explains the enemy's devious weapons, skills, and tactics and offers field-tested remedies, case studies, and testing labs. You will get complete coverage of Internet of Things, mobile, and Cloud security along with penetration testing, malware analysis, and reverse engineering techniques. State-of-the-art malware, ransomware, and system exploits are thoroughly explained. Fully revised content includes 7 new chapters covering the latest threats Includes proof-of-concept code stored on the GitHub repository Authors train attendees at major security conferences, including RSA, Black Hat, Defcon, and B-Sides

Ver na Amazon
Bloqueador USB de privacidade de porta USB para PC, notebook, bloco de laptop,

Bloqueador USB de privacidade de porta USB para PC, notebook, bloco de laptop,

Proteção de privacidade aprimorada: protege o link de transmissão de dados para evitar roubo de informações, fornecendo proteção de segurança robusta que protege a privacidade do usuário durante transferências de arquivos e garante uma conexão segura para interações de dispositivos sem preocupações em vários ambientes Uso a longo prazo: a camada protetora resistente ao desgaste, combinada com um corpo de metal resistente, oferece gerenciamento de calor confiável e qualidade duradoura durante o uso diário Entrega eficiente de energia: a tecnologia de chip inteligente garante a identificação automática dos requisitos de energia, fornecendo carregamento eficiente alinhando-se com vários protocolos de carregamento rápido para maior conveniência Proteção contra sobrecarga: evitando riscos de sobrecarga, este bloqueador de dados USB protege a vida útil da bateria e garante um desempenho estável, mantendo um fluxo estável de energia para melhorar a longevidade do dispositivo de forma eficaz Prático de transportar: com atenção à portabilidade, este bloqueador de dados USB oferece um design compacto que é leve e fácil de transportar, melhorando a conveniência do usuário e operação eficiente

Ver na Amazon

📩 Newsletter MundiX

Receba novidades de cibersegurança + um checklist de pentest grátis. Sem spam.

Ao assinar você concorda em receber e-mails. Cancele quando quiser.