Documentation
¶
Overview ¶
Package dnsoverhttps implements a DNS-over-HTTPS transport.
The API is intentionally small and designed for measurement use cases.
Example (WithLocalServer) ¶
package main
import (
"context"
"crypto/tls"
"fmt"
"net"
"net/http"
"net/netip"
"slices"
"github.com/bassosimone/dnscodec"
"github.com/bassosimone/dnsoverhttps"
"github.com/bassosimone/dnstest"
"github.com/bassosimone/pkitest"
"github.com/bassosimone/runtimex"
"github.com/miekg/dns"
)
func main() {
// 1. Create PKI for testing
//
// See https://github.com/bassosimone/pkitest
pki := pkitest.MustNewPKI("testdata")
certConfig := &pkitest.SelfSignedCertConfig{
CommonName: "example.com",
DNSNames: []string{"example.com"},
IPAddrs: []net.IP{net.IPv4(127, 0, 0, 1)},
Organization: []string{"Example"},
}
cert := pki.MustNewCert(certConfig)
clientConfig := &tls.Config{RootCAs: pki.CertPool()}
// 2. Create DNS server for testing
//
// See https://github.com/bassosimone/dnstest
dnsConfig := dnstest.NewHandlerConfig()
dnsConfig.AddNetipAddr("dns.google", netip.MustParseAddr("8.8.4.4"))
dnsConfig.AddNetipAddr("dns.google", netip.MustParseAddr("8.8.8.8"))
dnsHandler := dnstest.NewHandler(dnsConfig)
srv := dnstest.MustNewHTTPSServer(&net.ListenConfig{}, "127.0.0.1:0", cert, dnsHandler)
defer srv.Close()
// 3. Create the DNS transport
httpClient := &http.Client{Transport: &http.Transport{TLSClientConfig: clientConfig}}
dt := dnsoverhttps.NewTransport(httpClient, srv.URL())
// 4. Create the query
query := dnscodec.NewQuery("dns.google", dns.TypeA)
// 5. Exchange with the server
ctx := context.Background()
resp := runtimex.PanicOnError1(dt.Exchange(ctx, query))
// 6. Obtain the A records from the response
addrs := runtimex.PanicOnError1(resp.RecordsA())
// 7. Sort and print the addresses
slices.Sort(addrs)
fmt.Printf("%+v\n", addrs)
}
Output: [8.8.4.4 8.8.8.8]
Index ¶
- func NewRequest(ctx context.Context, query *dnscodec.Query, URL string) (*http.Request, *dns.Msg, error)
- func NewRequestWithHook(ctx context.Context, query *dnscodec.Query, URL string, ...) (*http.Request, *dns.Msg, error)
- func ReadResponse(ctx context.Context, resp *http.Response, query *dns.Msg) (*dnscodec.Response, error)
- func ReadResponseWithHook(ctx context.Context, httpResp *http.Response, queryMsg *dns.Msg, ...) (*dnscodec.Response, error)
- type Client
- type Transport
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NewRequest ¶
func NewRequest(ctx context.Context, query *dnscodec.Query, URL string) (*http.Request, *dns.Msg, error)
NewRequest serializes a DNS query message into an HTTP request.
Returns the HTTP request ready for the round trip and the *dns.Msg query, which is required later on to properly validate the DNS response.
func NewRequestWithHook ¶
func NewRequestWithHook(ctx context.Context, query *dnscodec.Query, URL string, observeHook func([]byte)) (*http.Request, *dns.Msg, error)
NewRequestWithHook is like NewRequest but calls observeHook with a copy of the raw DNS query after serialization. If observeHook is nil, it is not called.
func ReadResponse ¶
func ReadResponse(ctx context.Context, resp *http.Response, query *dns.Msg) (*dnscodec.Response, error)
ReadResponse reads and validates a DNS response as the response for the given query.
Because this function reads the whole response body, it closes it when done.
The context is used to interrupt reading the round trip or reading the response body.
func ReadResponseWithHook ¶
func ReadResponseWithHook(ctx context.Context, httpResp *http.Response, queryMsg *dns.Msg, observeHook func([]byte)) (*dnscodec.Response, error)
ReadResponseWithHook is like ReadResponse but calls observeHook with a copy of the raw DNS response after reading. If observeHook is nil, it is not called.
Types ¶
type Client ¶
Client abstracts over *http.Client.
type Transport ¶
type Transport struct {
// Client is the [Client] to use to exchange a query for a response.
//
// Set by [NewTransport] to the user-provided value.
Client Client
// URL is the server URL to use to exchange a query for a response.
//
// Set by [NewTransport] to the user-provided value.
URL string
// ObserveRawQuery is an optional hook called with a copy of the raw DNS query.
ObserveRawQuery func([]byte)
// ObserveRawResponse is an optional hook called with a copy of the raw DNS response.
ObserveRawResponse func([]byte)
}
Transport is a DNS-over-HTTPS transport.
Construct using NewTransport.
func NewTransport ¶
NewTransport creates a new *Transport.