DEV Community

Cover image for DoH: como funciona a consulta DNS no Clear Address?
Rodrigo de Avila
Rodrigo de Avila

Posted on

DoH: como funciona a consulta DNS no Clear Address?

Olá, pessoal!

Recentemente, o valterpatrick sugeriu que mostrasse como as consultas DNS são realizadas no site clear-address.rda.run. Agradeço muito pela pergunta, pois ela abre espaço para discutirmos um tema que considero fascinante e muito útil: DNS over HTTPS (DoH).

Em vez de usar o protocolo DNS tradicional, que geralmente opera de forma não criptografada na porta 53, o site utiliza as APIs públicas de resolvedores DNS que suportam HTTPS. Na prática, isso significa que uma consulta DNS se transforma em uma simples chamada HTTP. Isso traz uma camada extra de privacidade e segurança, pois a consulta se camufla como tráfego HTTPS comum.

A Mágica por Trás da Cortina: As APIs

O backend do Clear Address faz chamadas para resolvedores DoH, como os oferecidos pela Cloudflare e pelo Google. A escolha entre eles pode variar, mas o princípio é exatamente o mesmo.

A ideia é enviar uma requisição GET para um endpoint específico, passando o domínio e o tipo de registro desejado como parâmetros na URL. O servidor responde com um JSON contendo os resultados da consulta.

DoH via Cloudflare

A Cloudflare é uma das provedoras mais conhecidas de serviços DoH. A documentação completa pode ser encontrada aqui.

Para consultar o registro AAAA (endereço IPv6) do próprio clear-address.rda.run, a URL da API fica assim:

https://cloudflare-dns.com/dns-query?name=clear-address.rda.run&type=AAAA
Enter fullscreen mode Exit fullscreen mode

Usando cURL

Você pode testar isso diretamente no seu terminal com o cURL. O header Accept é importante para garantir que a Cloudflare nos devolva uma resposta em JSON.

curl -H 'Accept: application/dns-json' 'https://cloudflare-dns.com/dns-query?name=clear-address.rda.run&type=AAAA'
Enter fullscreen mode Exit fullscreen mode

Usando Go

No backend, o processo é similar. Aqui está um exemplo simples em Go de como fazer essa chamada e processar a resposta.

package main

import (
    "encoding/json"
    "fmt"
    "io"
    "net/http"
)

// Estrutura para receber a resposta da API da Cloudflare
type DNSResponse struct {
    Status   int  `json:"Status"`
    TC       bool `json:"TC"`
    RD       bool `json:"RD"`
    RA       bool `json:"RA"`
    AD       bool `json:"AD"`
    CD       bool `json:"CD"`
    Question []struct {
        Name string `json:"name"`
        Type int    `json:"type"`
    } `json:"Question"`
    Answer []struct {
        Name string `json:"name"`
        Type int    `json:"type"`
        TTL  int    `json:"TTL"`
        Data string `json:"data"`
    } `json:"Answer"`
}

func main() {
    // URL da API da Cloudflare para a consulta desejada
    url := "https://cloudflare-dns.com/dns-query?name=clear-address.rda.run&type=AAAA"

    // Cria uma nova requisição
    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        panic(err)
    }

    // Adiciona o header 'Accept' para especificar o formato da resposta
    req.Header.Add("Accept", "application/dns-json")

    // Executa a requisição
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    // Lê o corpo da resposta
    body, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    // Decodifica o JSON na nossa struct
    var dnsResp DNSResponse
    if err := json.Unmarshal(body, &dnsResp); err != nil {
        panic(err)
    }

    // Imprime os resultados
    fmt.Println("Resultados da consulta DNS:")
    if len(dnsResp.Answer) > 0 {
        for _, answer := range dnsResp.Answer {
            fmt.Printf(" - Domínio: %s\n", answer.Name)
            fmt.Printf("   Tipo: AAAA\n")
            fmt.Printf("   TTL: %d\n", answer.TTL)
            fmt.Printf("   Endereço IPv6: %s\n", answer.Data)
        }
    } else {
        fmt.Println("Nenhum registro AAAA encontrado.")
    }
}
Enter fullscreen mode Exit fullscreen mode

DoH via Google

O Google oferece um serviço similar, documentado aqui. A lógica é a mesma, mudando apenas a URL.

https://dns.google/resolve?name=clear-address.rda.run&type=AAAA
Enter fullscreen mode Exit fullscreen mode

A implementação, seja com cURL ou Go, seguiria o mesmo padrão, adaptando-se apenas à estrutura do JSON de resposta do Google, que pode ter pequenas diferenças.

Backend vs. Frontend

Uma observação importante: no Clear Address, essas chamadas são sempre feitas pelo backend. Nunca tentei fazê-las diretamente pelo frontend (via JavaScript no navegador), então não sei dizer se haveria problemas com CORS (Cross-Origin Resource Sharing) ou a necessidade de algum header específico para que a requisição fosse aceita. Fazer pelo backend simplifica o processo e mantém a lógica de negócio no servidor.

Conclusão

E é isso! Sem grande complexidade, o Clear Address apenas utiliza as APIs públicas e bem documentadas de grandes players para resolver nomes de domínio de forma segura e privada.

Espero que este artigo tenha saciado a curiosidade e mostrado como é simples implementar algo parecido.

O que vocês acham dessa abordagem? Já usaram DoH em algum projeto? Deixem suas experiências e dúvidas nos comentários.

Um abraço.

Top comments (0)