DoH: how does DNS resolution work in ClearAddress?
Hi there!
Recently, valterpatrick suggested I show how DNS queries are made on the clear-address.rda.run website. I really appreciate the question, as it opens up a fascinating and very useful topic: DNS over HTTPS (DoH).
Instead of using the traditional DNS protocol, which typically operates unencrypted on port 53, the site uses the public APIs of DNS resolvers that support HTTPS. In practice, this means a DNS query is transformed into a simple HTTP call. This adds an extra layer of privacy and security, as the query is disguised as regular HTTPS traffic.
The Magic Behind the Curtain: The APIs
The backend of Clear Address makes calls to DoH resolvers, such as those offered by Cloudflare and Google. The choice between them may vary, but the principle is exactly the same.
The idea is to send a GET request to a specific endpoint, passing the domain and the desired record type as URL parameters. The server responds with a JSON containing the query results.
DoH via Cloudflare
Cloudflare is one of the most well-known providers of DoH services. The complete documentation can be found here.
To query the AAAA record (IPv6 address) of clear-address.rda.run itself, the API URL looks like this:
https://cloudflare-dns.com/dns-query?name=clear-address.rda.run&type=AAAAUsing cURL
You can test this directly in your terminal with cURL. The Accept header is important to ensure Cloudflare returns a JSON response.
curl -H 'Accept: application/dns-json' 'https://cloudflare-dns.com/dns-query?name=clear-address.rda.run&type=AAAA'Using Go
On the backend, the process is similar. Here is a simple example in Go of how to make this call and process the response.
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
)
// Struct to receive the Cloudflare API response
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() {
// Cloudflare API URL for the desired query
url := "https://cloudflare-dns.com/dns-query?name=clear-address.rda.run&type=AAAA"
// Create a new request
req, err := http.NewRequest("GET", url, nil)
if err != nil {
panic(err)
}
// Add the 'Accept' header to specify the response format
req.Header.Add("Accept", "application/dns-json")
// Execute the request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
// Read the response body
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
// Decode the JSON into our struct
var dnsResp DNSResponse
if err := json.Unmarshal(body, &dnsResp); err != nil {
panic(err)
}
// Print the results
fmt.Println("DNS query results:")
if len(dnsResp.Answer) > 0 {
for _, answer := range dnsResp.Answer {
fmt.Printf(" - Domain: %s\n", answer.Name)
fmt.Printf(" Type: AAAA\n")
fmt.Printf(" TTL: %d\n", answer.TTL)
fmt.Printf(" IPv6 Address: %s\n", answer.Data)
}
} else {
fmt.Println("No AAAA records found.")
}
}DoH via Google
Google offers a similar service, documented here. The logic is the same, only the URL changes.
https://dns.google/resolve?name=clear-address.rda.run&type=AAAAThe implementation, whether with cURL or Go, would follow the same pattern, adapting only to the structure of the Google response JSON, which may have minor differences.
Backend vs. Frontend
An important note: in Clear Address, these calls are always made by the backend. I've never tried to make them directly from the frontend (via JavaScript in the browser), so I can't say if there would be issues with CORS (Cross-Origin Resource Sharing) or if a specific header would be needed for the request to be accepted. Using the backend simplifies the process and keeps the business logic on the server.
Conclusion
And that's it! Without great complexity, Clear Address simply uses the public and well-documented APIs of major players to resolve domain names securely and privately.