Documentation ¶
Overview ¶
Package upstream implements DNS clients for all known DNS encryption protocols.
Index ¶
- Constants
- Variables
- func LookupParallel(ctx context.Context, resolvers []Resolver, host string) (addrs []netip.Addr, err error)deprecated
- type CachingResolver
- type ConsequentResolver
- type DialerInitializer
- type ExchangeAllResult
- type HTTPVersion
- type HostsResolver
- type NotBootstrapError
- type Options
- type ParallelResolver
- type QUICTraceFunc
- type Resolver
- type StaticResolver
- type Upstream
- type UpstreamResolver
Constants ¶
const ( // QUICCodeNoError is used when the connection or stream needs to be closed, // but there is no error to signal. QUICCodeNoError = quic.ApplicationErrorCode(0) // QUICCodeInternalError signals that the DoQ implementation encountered // an internal error and is incapable of pursuing the transaction or the // connection. QUICCodeInternalError = quic.ApplicationErrorCode(1) // QUICKeepAlivePeriod is the value that we pass to *quic.Config and that // controls the period with with keep-alive frames are being sent to the // connection. We set it to 20s as it would be in the quic-go@v0.27.1 with // KeepAlive field set to true This value is specified in // https://pkg.go.dev/github.com/quic-go/quic-go/internal/protocol#MaxKeepAliveInterval. // // TODO(ameshkov): Consider making it configurable. QUICKeepAlivePeriod = time.Second * 20 // NextProtoDQ is the ALPN token for DoQ. During the connection establishment, // DNS/QUIC support is indicated by selecting the ALPN token "doq" in the // crypto handshake. // // See https://datatracker.ietf.org/doc/rfc9250. NextProtoDQ = "doq" )
const ( // ErrNoUpstreams is returned from the methods that expect at least a single // upstream to work with when no upstreams specified. ErrNoUpstreams errors.Error = "no upstream specified" // ErrNoReply is returned from [ExchangeAll] when no upstreams replied. ErrNoReply errors.Error = "no reply" )
Variables ¶
var DefaultHTTPVersions = []HTTPVersion{HTTPVersion11, HTTPVersion2}
DefaultHTTPVersions is the list of HTTPVersion that we use by default in the DNS-over-HTTPS client.
Functions ¶
func LookupParallel
deprecated
Types ¶
type CachingResolver ¶
type CachingResolver struct {
// contains filtered or unexported fields
}
CachingResolver is a Resolver that caches the results of lookups. It's required to be created with NewCachingResolver.
func NewCachingResolver ¶
func NewCachingResolver(r *UpstreamResolver) (cr *CachingResolver)
NewCachingResolver creates a new caching resolver that uses r for lookups.
func (*CachingResolver) LookupNetIP ¶
func (r *CachingResolver) LookupNetIP( ctx context.Context, network bootstrap.Network, host string, ) (addrs []netip.Addr, err error)
LookupNetIP implements the Resolver interface for *CachingResolver.
TODO(e.burkov): It may appear that several concurrent lookup results rewrite each other in the cache.
type ConsequentResolver ¶
type ConsequentResolver = bootstrap.ConsequentResolver
ConsequentResolver is a slice of resolvers that are queried in order until the first successful non-empty response, as opposed to just successful response requirement in ParallelResolver.
type DialerInitializer ¶
type DialerInitializer func() (handler bootstrap.DialHandler, err error)
DialerInitializer returns the handler that it creates.
type ExchangeAllResult ¶
type ExchangeAllResult struct { // Resp is the response DNS request resolved into. Resp *dns.Msg // Upstream is the upstream that successfully resolved the request. Upstream Upstream }
ExchangeAllResult is the successful result of ExchangeAll for a single upstream.
func ExchangeAll ¶
func ExchangeAll(ups []Upstream, req *dns.Msg) (res []ExchangeAllResult, err error)
ExchangeAll returns the responses from all of u. It returns an error only if all upstreams failed to exchange the request.
type HTTPVersion ¶
type HTTPVersion string
HTTPVersion is an enumeration of the HTTP versions that we support. Values that we use in this enumeration are also used as ALPN values.
const ( // HTTPVersion11 is HTTP/1.1. HTTPVersion11 HTTPVersion = "http/1.1" // HTTPVersion2 is HTTP/2. HTTPVersion2 HTTPVersion = "h2" // HTTPVersion3 is HTTP/3. HTTPVersion3 HTTPVersion = "h3" )
type HostsResolver ¶
type HostsResolver struct {
// contains filtered or unexported fields
}
HostsResolver is a Resolver that looks into system hosts files, see hostsfile.
func NewDefaultHostsResolver ¶
func NewDefaultHostsResolver(rootFSys fs.FS) (hr *HostsResolver, err error)
NewDefaultHostsResolver returns a resolver based on system hosts files provided by the hostsfile.DefaultHostsPaths and read from rootFSys.
func NewHostsResolver ¶
func NewHostsResolver(hosts hostsfile.Storage) (hr *HostsResolver)
NewHostsResolver is the resolver based on system hosts files.
type NotBootstrapError ¶
type NotBootstrapError struct {
// contains filtered or unexported fields
}
NotBootstrapError is returned by AddressToUpstream when the parsed upstream can't be used as a bootstrap and wraps the actual reason.
func (NotBootstrapError) Error ¶
func (e NotBootstrapError) Error() (msg string)
Error implements the [error] interface for NotBootstrapError.
func (NotBootstrapError) Unwrap ¶
func (e NotBootstrapError) Unwrap() (reason error)
Unwrap implements the errors.Wrapper interface.
type Options ¶
type Options struct { // VerifyServerCertificate is used to set the VerifyPeerCertificate property // of the *tls.Config for DNS-over-HTTPS, DNS-over-QUIC, and DNS-over-TLS. VerifyServerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error // VerifyConnection is used to set the VerifyConnection property // of the *tls.Config for DNS-over-HTTPS, DNS-over-QUIC, and DNS-over-TLS. VerifyConnection func(state tls.ConnectionState) error // VerifyDNSCryptCertificate is the callback the DNSCrypt server certificate // will be passed to. It's called in dnsCrypt.exchangeDNSCrypt. // Upstream.Exchange method returns any error caused by it. VerifyDNSCryptCertificate func(cert *dnscrypt.Cert) error // QUICTracer is an optional callback that allows tracing every QUIC // connection and logging every packet that goes through. QUICTracer QUICTraceFunc // RootCAs is the CertPool that must be used by all upstreams. Redefining // RootCAs makes sense on iOS to overcome the 15MB memory limit of the // NEPacketTunnelProvider. RootCAs *x509.CertPool // CipherSuites is a custom list of TLSv1.2 ciphers. CipherSuites []uint16 // Bootstrap is used to resolve upstreams' hostnames. If nil, the // [net.DefaultResolver] will be used. Bootstrap Resolver // HTTPVersions is a list of HTTP versions that should be supported by the // DNS-over-HTTPS client. If not set, HTTP/1.1 and HTTP/2 will be used. HTTPVersions []HTTPVersion // Timeout is the default upstream timeout. It's also used as a timeout for // bootstrap DNS requests. Zero value disables the timeout. Timeout time.Duration // InsecureSkipVerify disables verifying the server's certificate. InsecureSkipVerify bool // PreferIPv6 tells the bootstrapper to prefer IPv6 addresses for an // upstream. PreferIPv6 bool }
Options for AddressToUpstream func. With these options we can configure the upstream properties.
type ParallelResolver ¶
type ParallelResolver = bootstrap.ParallelResolver
ParallelResolver is a slice of resolvers that are queried concurrently until the first successful response is returned, as opposed to all resolvers being queried in order in ConsequentResolver.
type QUICTraceFunc ¶
type QUICTraceFunc func( ctx context.Context, role logging.Perspective, connID quic.ConnectionID, ) (tracer *logging.ConnectionTracer)
QUICTraceFunc is a function that returns a logging.ConnectionTracer specific for a given role and connection ID.
type Resolver ¶
Resolver resolves the hostnames to IP addresses. Note, that net.Resolver from standard library also implements this interface.
type StaticResolver ¶
type StaticResolver = bootstrap.StaticResolver
StaticResolver is a resolver which always responds with an underlying slice of IP addresses.
type Upstream ¶
type Upstream interface { // Exchange sends the DNS query req to this upstream and returns the // response that has been received or an error if something went wrong. Exchange(req *dns.Msg) (resp *dns.Msg, err error) // Address returns the address of the upstream DNS resolver. Address() (addr string) // Closer used to close the upstreams properly. Exchange shouldn't be // called after calling Close. io.Closer }
Upstream is an interface for a DNS resolver.
func AddressToUpstream ¶
AddressToUpstream converts addr to an Upstream using the specified options. addr can be either a URL, or a plain address, either a domain name or an IP.
- 1.2.3.4 or 1.2.3.4:4321 for plain DNS using IP address;
- udp://5.3.5.3:53 or 5.3.5.3:53 for plain DNS using IP address;
- udp://name.server:53 or name.server:53 for plain DNS using domain name;
- tcp://5.3.5.3:53 for plain DNS-over-TCP using IP address;
- tcp://name.server:53 for plain DNS-over-TCP using domain name;
- tls://5.3.5.3:853 for DNS-over-TLS using IP address;
- tls://name.server:853 for DNS-over-TLS using domain name;
- https://5.3.5.3:443/dns-query for DNS-over-HTTPS using IP address;
- https://name.server:443/dns-query for DNS-over-HTTPS using domain name;
- quic://5.3.5.3:853 for DNS-over-QUIC using IP address;
- quic://name.server:853 for DNS-over-QUIC using domain name;
- h3://dns.google for DNS-over-HTTPS that only works with HTTP/3;
- sdns://... for DNS stamp, see https://dnscrypt.info/stamps-specifications.
If addr doesn't have port specified, the default port of the appropriate protocol will be used.
opts are applied to the u and shouldn't be modified afterwards, nil value is valid.
TODO(e.burkov): Clone opts?
type UpstreamResolver ¶
type UpstreamResolver struct { // Upstream is used for lookups. It must not be nil. Upstream }
UpstreamResolver is a wrapper around Upstream that implements the bootstrap.Resolver interface.
func NewUpstreamResolver ¶
func NewUpstreamResolver(resolverAddress string, opts *Options) (r *UpstreamResolver, err error)
NewUpstreamResolver creates an upstream that can be used as bootstrap Resolver. resolverAddress format is the same as in the AddressToUpstream. If the upstream can't be used as a bootstrap, the returned error will have the underlying type of NotBootstrapError, and r itself will be fully usable. Closing r.Upstream is caller's responsibility.
func (*UpstreamResolver) LookupNetIP ¶
func (r *UpstreamResolver) LookupNetIP( ctx context.Context, network bootstrap.Network, host string, ) (ips []netip.Addr, err error)
LookupNetIP implements the Resolver interface for *UpstreamResolver. It doesn't consider the TTL of the DNS records.
TODO(e.burkov): Investigate why the empty slice is returned instead of nil.