proxy

package
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 8, 2026 License: Apache-2.0 Imports: 51 Imported by: 0

Documentation

Overview

Package proxy implements a DNS proxy that supports all known DNS encryption protocols.

Index

Constants

View Source
const (
	// DefaultOptimisticMaxAge is default value for
	// [Config.CacheOptimisticMaxAge].
	DefaultOptimisticMaxAge = 12 * time.Hour

	// DefaultOptimisticAnswerTTL is default value for
	// [Config.CacheOptimisticAnswerTTL].
	DefaultOptimisticAnswerTTL = 30 * time.Second
)
View Source
const (
	// DoQCodeNoError is used when the connection or stream needs to be closed,
	// but there is no error to signal.
	DoQCodeNoError quic.ApplicationErrorCode = 0
	// DoQCodeInternalError signals that the DoQ implementation encountered
	// an internal error and is incapable of pursuing the transaction or the
	// connection.
	DoQCodeInternalError quic.ApplicationErrorCode = 1
	// DoQCodeProtocolError signals that the DoQ implementation encountered
	// a protocol error and is forcibly aborting the connection.
	DoQCodeProtocolError quic.ApplicationErrorCode = 2
)
View Source
const ErrDrop errors.Error = "drop response"

ErrDrop is returned by a Handler to signal that the proxy should not send any response to the client.

View Source
const ErrEmptyHost = errors.Error("host is empty")

ErrEmptyHost is returned by LookupIPAddr when the host is empty and can't be resolved.

View Source
const LogPrefix = "dnsproxy"

LogPrefix is a prefix for logging.

View Source
const (

	// NAT64PrefixLength is the length of a NAT64 prefix in bytes.
	NAT64PrefixLength = net.IPv6len - net.IPv4len
)
View Source
const NextProtoDQ = "doq"

NextProtoDQ is the ALPN token for DoQ. During connection establishment, DNS/QUIC support is indicated by selecting the ALPN token "dq" in the crypto handshake. DoQ RFC: https://www.rfc-editor.org/rfc/rfc9250.html

View Source
const ServFailMaxCacheTTL = 30

ServFailMaxCacheTTL is the maximum time-to-live value for caching SERVFAIL responses in seconds. It's consistent with the upper constraint of 5 minutes given by RFC 2308.

See https://datatracker.ietf.org/doc/html/rfc2308#section-7.1.

View Source
const UnqualifiedNames = "unqualified_names"

UnqualifiedNames is a key for [UpstreamConfig.DomainReservedUpstreams] map to specify the upstreams only used for resolving domain names consisting of a single label.

Variables

This section is empty.

Functions

func ValidatePrivateConfig

func ValidatePrivateConfig(uc *UpstreamConfig, privateSubnets netutil.SubnetSet) (err error)

ValidatePrivateConfig returns an error if uc isn't valid, or, treated as private upstreams configuration, contains specifications for invalid domains.

Types

type BindRetryConfig

type BindRetryConfig struct {
	// Interval is the minimum time to wait after the latest failure.  It must
	// not be negative if Enabled is true.
	Interval time.Duration

	// Count is the maximum number of retries after the first attempt.
	Count uint

	// Enabled indicates whether the binding should be retried.
	Enabled bool
}

BindRetryConfig contains configuration for the listeners binding retry mechanism.

type Config

type Config struct {
	// Logger is used as the base logger for the proxy service.  If nil,
	// [slog.Default] with [LogPrefix] is used.
	Logger *slog.Logger

	// TrustedProxies is the trusted list of CIDR networks to detect proxy
	// servers addresses from where the DoH requests should be handled.  The
	// value of nil makes Proxy not trust any address.
	TrustedProxies netutil.SubnetSet

	// PrivateSubnets is the set of private networks.  Client having an address
	// within this set is able to resolve PTR requests for addresses within this
	// set.
	PrivateSubnets netutil.SubnetSet

	// MessageConstructor used to build DNS messages.  If nil, the default
	// constructor will be used.
	MessageConstructor MessageConstructor

	// PendingRequests is used to mitigate the cache poisoning attacks by
	// tracking identical requests and returning the same response for them,
	// performing a single lookup.  If nil, it will be enabled by default.
	PendingRequests *PendingRequestsConfig

	// RequestContext is a context constructor that returns contexts for
	// requests.  If not set, the proxy uses [contextutil.EmptyConstructor].
	RequestContext contextutil.Constructor

	// RequestHandler is an optional custom handler for DNS requests.  It's used
	// instead of DefaultHandler if set.  In case of [ErrDrop] error returned
	// from this handler, the proxy will not send any response to the client.
	RequestHandler Handler

	// UpstreamConfig is a general set of DNS servers to forward requests to.
	UpstreamConfig *UpstreamConfig

	// PrivateRDNSUpstreamConfig is the set of upstream DNS servers for
	// resolving private IP addresses.  All the requests considered private will
	// be resolved via these upstream servers.  Such queries will finish with
	// [upstream.ErrNoUpstream] if it's empty.
	PrivateRDNSUpstreamConfig *UpstreamConfig

	// Fallbacks is a list of fallback resolvers.  Those will be used if the
	// general set fails responding.  It isn't allowed to be empty, but can be
	// nil, which means not to use fallbacks.
	//
	// TODO(e.burkov):  Add explicit boolean for disabling fallbacks.
	Fallbacks *UpstreamConfig

	// TLSConfig is the TLS configuration.  Required for DNS-over-TLS,
	// DNS-over-HTTP, and DNS-over-QUIC servers.
	TLSConfig *tls.Config

	// DNSCryptResolverCert is the DNSCrypt resolver certificate.  Required for
	// DNSCrypt server.
	DNSCryptResolverCert *dnscrypt.Cert

	// BindRetryConfig configures the listeners binding retrying.  If nil,
	// retries are disabled.
	BindRetryConfig *BindRetryConfig

	// HTTPConfig is the configuration for HTTP requests proxying.  Required for
	// DoH server.  If nil, the DoH server is disabled.
	HTTPConfig *HTTPConfig

	// DNSCryptProviderName is the DNSCrypt provider name.  Required for
	// DNSCrypt server.
	DNSCryptProviderName string

	// UpstreamMode determines the logic through which upstreams will be used.
	// If not specified the [proxy.UpstreamModeLoadBalance] is used.
	UpstreamMode UpstreamMode

	// UDPListenAddr is the set of UDP addresses to listen for plain
	// DNS-over-UDP requests.
	UDPListenAddr []*net.UDPAddr

	// TCPListenAddr is the set of TCP addresses to listen for plain
	// DNS-over-TCP requests.
	TCPListenAddr []*net.TCPAddr

	// TLSListenAddr is the set of TCP addresses to listen for DNS-over-TLS
	// requests.
	TLSListenAddr []*net.TCPAddr

	// QUICListenAddr is the set of UDP addresses to listen for DNS-over-QUIC
	// requests.
	QUICListenAddr []*net.UDPAddr

	// DNSCryptUDPListenAddr is the set of UDP addresses to listen for DNSCrypt
	// requests.
	DNSCryptUDPListenAddr []*net.UDPAddr

	// DNSCryptTCPListenAddr is the set of TCP addresses to listen for DNSCrypt
	// requests.
	DNSCryptTCPListenAddr []*net.TCPAddr

	// BogusNXDomain is the set of networks used to transform responses into
	// NXDOMAIN ones if they contain at least a single IP address within these
	// networks.  It's similar to dnsmasq's "bogus-nxdomain".
	BogusNXDomain []netip.Prefix

	// DNS64Prefs is the set of NAT64 prefixes used for DNS64 handling.  nil
	// value disables the feature.  An empty value will be interpreted as the
	// default Well-Known Prefix.
	DNS64Prefs []netip.Prefix

	// EDNSAddr is the ECS IP used in request.
	EDNSAddr net.IP

	// CacheSizeBytes is the maximum cache size in bytes.
	CacheSizeBytes int

	// CacheMinTTL is the minimum TTL for cached DNS responses in seconds.
	CacheMinTTL uint32

	// CacheMaxTTL is the maximum TTL for cached DNS responses in seconds.
	CacheMaxTTL uint32

	// CacheOptimisticAnswerTTL is the default TTL for expired cached responses.
	// Default value is [DefaultOptimisticAnswerTTL].
	CacheOptimisticAnswerTTL time.Duration

	// CacheOptimisticMaxAge is the maximum time entries remain in the cache
	// when cache is optimistic.  Default value is [DefaultOptimisticMaxAge].
	CacheOptimisticMaxAge time.Duration

	// MaxGoroutines is the maximum number of goroutines processing DNS
	// requests.  Important for mobile users.
	//
	// TODO(a.garipov): Rename this to something like “MaxDNSRequestGoroutines”
	// in a later major version, as it doesn't actually limit all goroutines.
	MaxGoroutines uint

	// The size of the read buffer on the underlying socket.  Larger read
	// buffers can handle larger bursts of requests before packets get dropped.
	UDPBufferSize int

	// FastestPingTimeout is the timeout for waiting the first successful
	// dialing when the UpstreamMode is set to [UpstreamModeFastestAddr].
	// Non-positive value will be replaced with the default one.
	FastestPingTimeout time.Duration

	// RefuseAny makes proxy refuse the requests of type ANY.
	RefuseAny bool

	// TCPProxyProtocolV2Enabled defines whether plain DNS-over-TCP listeners
	// require Proxy Protocol v2 headers.
	TCPProxyProtocolV2Enabled bool

	// TLSProxyProtocolV2Enabled defines whether DNS-over-TLS listeners require
	// Proxy Protocol v2 headers before TLS handshake.
	TLSProxyProtocolV2Enabled bool

	// ProxyProtocolV2ReadTimeout bounds the pre-DNS stage when waiting for the
	// PPv2 signature and payload from a newly accepted connection.
	//
	// Zero value means using a built-in default.
	ProxyProtocolV2ReadTimeout time.Duration

	// DNSSECEnabled specifies if the proxy should set the DO bits in the
	// upstream requests.
	DNSSECEnabled bool

	// Enable EDNS Client Subnet option DNS requests to the upstream server will
	// contain an OPT record with Client Subnet option.  If the original request
	// already has this option set, we pass it through as is.  Otherwise, we set
	// it ourselves using the client IP with subnet /24 (for IPv4) and /56 (for
	// IPv6).
	//
	// If the upstream server supports ECS, it sets subnet number in the
	// response.  This subnet number along with the client IP and other data is
	// used as a cache key.  Next time, if a client from the same subnet
	// requests this host name, we get the response from cache.  If another
	// client from a different subnet requests this host name, we pass his
	// request to the upstream server.
	//
	// If the upstream server doesn't support ECS (there's no subnet number in
	// response), this response will be cached for all clients.
	//
	// If client IP is private (i.e. not public), we don't add EDNS record into
	// a request.  And so there will be no EDNS record in response either.  We
	// store these responses in general cache (without subnet) so they will
	// never be used for clients with public IP addresses.
	EnableEDNSClientSubnet bool

	// CacheEnabled defines if the response cache should be used.
	CacheEnabled bool

	// CacheOptimistic defines if the optimistic cache mechanism should be used.
	CacheOptimistic bool

	// UseDNS64 enables DNS64 handling.  If true, proxy will translate IPv4
	// answers into IPv6 answers using first of DNS64Prefs.  Note also that PTR
	// requests for addresses within the specified networks are considered
	// private and will be forwarded as PrivateRDNSUpstreamConfig specifies.
	// Those will be responded with NXDOMAIN if UsePrivateRDNS is false.
	UseDNS64 bool

	// UsePrivateRDNS defines if the PTR requests for private IP addresses
	// should be resolved via PrivateRDNSUpstreamConfig.  Note that it requires
	// a valid PrivateRDNSUpstreamConfig with at least a single general upstream
	// server.
	UsePrivateRDNS bool

	// PreferIPv6 tells the proxy to prefer IPv6 addresses when bootstrapping
	// upstreams that use hostnames.
	PreferIPv6 bool
}

Config contains all the fields necessary for proxy configuration.

TODO(a.garipov): Consider extracting conf blocks for better fieldalignment.

type CustomUpstreamConfig

type CustomUpstreamConfig struct {
	// contains filtered or unexported fields
}

CustomUpstreamConfig contains upstreams configuration with an optional cache.

func NewCustomUpstreamConfig

func NewCustomUpstreamConfig(
	u *UpstreamConfig,
	cacheEnabled bool,
	cacheSize int,
	enableEDNSClientSubnet bool,
) (c *CustomUpstreamConfig)

NewCustomUpstreamConfig returns new custom upstream configuration.

func (*CustomUpstreamConfig) ClearCache

func (c *CustomUpstreamConfig) ClearCache()

ClearCache removes all items from the cache.

func (*CustomUpstreamConfig) Close

func (c *CustomUpstreamConfig) Close() (err error)

Close closes the custom upstream config.

type DNSContext

type DNSContext struct {
	// Conn is the underlying client connection.  It is nil if Proto is
	// ProtoDNSCrypt, ProtoHTTPS, or ProtoQUIC.
	Conn net.Conn

	// QUICConnection is the QUIC session from which we got the query.  For
	// ProtoQUIC only.
	QUICConnection *quic.Conn

	// QUICStream is the QUIC stream from which we got the query.  For
	// [ProtoQUIC] only.
	QUICStream *quic.Stream

	// Upstream is the upstream that resolved the request.  In case of cached
	// response it's nil.
	Upstream upstream.Upstream

	// DNSCryptResponseWriter - necessary to respond to a DNSCrypt query
	DNSCryptResponseWriter dnscrypt.ResponseWriter

	// HTTPResponseWriter - HTTP response writer (for DoH only)
	HTTPResponseWriter http.ResponseWriter

	// HTTPRequest - HTTP request (for DoH only)
	HTTPRequest *http.Request

	// ReqECS is the EDNS Client Subnet used in the request.
	ReqECS *net.IPNet

	// CustomUpstreamConfig is the upstreams configuration used only for current
	// request.  The Resolve method of Proxy uses it instead of the default
	// servers if it's not nil.
	CustomUpstreamConfig *CustomUpstreamConfig

	// Req is the request message.
	Req *dns.Msg

	// Res is the response message.
	Res *dns.Msg

	// Proto is the DNS protocol of the query.
	Proto Proto

	// RequestedPrivateRDNS is the subnet extracted from the ARPA domain of
	// request's question if it's a PTR, SOA, or NS query for a private IP
	// address.  It can be a single-address subnet as well as a zero-length one.
	RequestedPrivateRDNS netip.Prefix

	// Addr is the address of the client.
	Addr netip.AddrPort

	// DoQVersion is the DoQ protocol version. It can (and should) be read from
	// ALPN, but in the current version we also use the way DNS messages are
	// encoded as a signal.
	DoQVersion DoQVersion

	// RequestID is an opaque numerical identifier of this request that is
	// guaranteed to be unique across requests processed by a single Proxy
	// instance.
	RequestID uint64

	// IsPrivateClient is true if the client's address is considered private
	// according to the configured private subnet set.
	IsPrivateClient bool
	// contains filtered or unexported fields
}

DNSContext represents a DNS request message context

func (*DNSContext) QueryStatistics

func (dctx *DNSContext) QueryStatistics() (s *QueryStatistics)

QueryStatistics returns the DNS query statistics for both the upstream and fallback DNS servers. The returned statistics will be nil until a DNS lookup has been performed.

Depending on whether the DNS request was successfully resolved and the upstream mode, the returned statistics consist of:

  • If the query was successfully resolved, the statistics contain the DNS lookup duration for the main resolver.

  • If the query was retrieved from the cache, the statistics will contain a single entry of UpstreamStatistics where the property IsCached is set to true.

  • If the upstream mode is UpstreamModeFastestAddr and the query was successfully resolved, the statistics contain the DNS lookup durations or errors for each main upstream.

  • If the query was resolved by the fallback resolver, the statistics contain the DNS lookup errors for each main upstream and the query duration for the fallback resolver.

  • If the query was not resolved at all, the statistics contain the DNS lookup errors for each main and fallback resolvers.

Both s and any data returned from its methods must not be modified.

type DefaultHandler

type DefaultHandler struct{}

DefaultHandler implements Handler by calling Proxy.Resolve. It is used as a default handler if no other handler is specified.

func (DefaultHandler) ServeDNS

func (DefaultHandler) ServeDNS(ctx context.Context, p *Proxy, proxyCtx *DNSContext) (err error)

ServeDNS implements the Handler interface for DefaultHandler.

type DoQVersion

type DoQVersion int

DoQVersion is an enumeration with supported DoQ versions.

const (
	// DoQv1Draft represents old DoQ draft versions that do not send a 2-octet
	// prefix with the DNS message length.
	//
	// TODO(ameshkov): remove in the end of 2024.
	DoQv1Draft DoQVersion = 0x00

	// DoQv1 represents DoQ v1.0: https://www.rfc-editor.org/rfc/rfc9250.html.
	DoQv1 DoQVersion = 0x01
)

type HTTPConfig

type HTTPConfig struct {
	// Userinfo is the sole permitted userinfo for the DoH basic authentication.
	// If Userinfo is set, all DoH queries are required to have this basic
	// authentication information.
	Userinfo *url.Userinfo

	// ServerHeader sets the Server header of the HTTPS server responses, if not
	// empty.
	ServerHeader string

	// ListenAddresses is the set of addresses to listen for DNS-over-HTTPS
	// requests.  If it is empty the proxy doesn't start the HTTPS server, but
	// still can be used as an http.Handler with [Proxy.ServeHTTP].
	ListenAddresses []netip.AddrPort

	// Routes is the set of routes to handle.  It must be a slice of valid route
	// patterns, if it is empty, the default routes are registered.  It is
	// ignored if ListenAddresses is empty.
	Routes []string

	// ReadTimeout is the maximum duration before timing out reads of the
	// request.  A zero or negative value means there will be no timeout.  It is
	// ignored if ListenAddresses is empty.
	ReadTimeout time.Duration

	// WriteTimeout is the maximum duration before timing out writes of the
	// response.  A zero or negative value means there will be no timeout.  It
	// is ignored if ListenAddresses is empty.
	WriteTimeout time.Duration

	// HTTP3Enabled specifies if HTTP/3 support for HTTPS server.  It is ignored
	// if ListenAddresses is empty.
	HTTP3Enabled bool

	// InsecureEnabled specifies if unencrypted DoH requests are allowed.
	InsecureEnabled bool
}

HTTPConfig is the configuration for HTTP requests proxying.

type Handler

type Handler interface {
	// ServeDNS resolves the DNS request within *DNSContext.
	ServeDNS(ctx context.Context, p *Proxy, dctx *DNSContext) (err error)
}

Handler is an interface for handling DNS requests.

func PassThrough

func PassThrough(h Handler) (wrapped Handler)

PassThrough is a MiddlewareFunc that returns h as-is.

type HandlerFunc

type HandlerFunc func(ctx context.Context, p *Proxy, dctx *DNSContext) (err error)

The HandlerFunc type is an adapter to allow the use of ordinary functions as Handler. If f is a function with the appropriate signature, HandlerFunc(f) is a Handler that calls f.

func (HandlerFunc) ServeDNS

func (f HandlerFunc) ServeDNS(ctx context.Context, p *Proxy, dctx *DNSContext) (err error)

ServeDNS implements the Handler interface for HandlerFunc.

type MessageConstructor

type MessageConstructor = dnsmsg.MessageConstructor

MessageConstructor creates DNS messages.

type Middleware

type Middleware interface {
	// Wrap returns a new handler that wraps the specified handler.
	Wrap(handler Handler) (wrapped Handler)
}

Middleware is a common middleware interface.

type MiddlewareFunc

type MiddlewareFunc func(h Handler) (wrapped Handler)

MiddlewareFunc is a function that implements the Middleware interface.

func (MiddlewareFunc) Wrap

func (f MiddlewareFunc) Wrap(h Handler) (wrapped Handler)

Wrap implements the Middleware interface for MiddlewareFunc.

type ParseError

type ParseError struct {

	// Idx is an index of the lines.  See [ParseUpstreamsConfig].
	Idx int
	// contains filtered or unexported fields
}

ParseError is an error which contains an index of the line of the upstream list.

func (*ParseError) Error

func (e *ParseError) Error() (msg string)

Error implements the [error] interface for *ParseError.

func (*ParseError) Unwrap

func (e *ParseError) Unwrap() (unwrapped error)

Unwrap implements the errors.Wrapper interface for *ParseError.

type PendingRequestsConfig

type PendingRequestsConfig struct {
	// Enabled defines if the duplicate requests should be tracked.
	Enabled bool
}

PendingRequestsConfig is the configuration for tracking identical requests.

type Proto

type Proto string

Proto is the DNS protocol.

const (
	// ProtoUDP is the plain DNS-over-UDP protocol.
	ProtoUDP Proto = "udp"
	// ProtoTCP is the plain DNS-over-TCP protocol.
	ProtoTCP Proto = "tcp"
	// ProtoTLS is the DNS-over-TLS (DoT) protocol.
	ProtoTLS Proto = "tls"
	// ProtoHTTPS is the DNS-over-HTTPS (DoH) protocol.
	ProtoHTTPS Proto = "https"
	// ProtoQUIC is the DNS-over-QUIC (DoQ) protocol.
	ProtoQUIC Proto = "quic"
	// ProtoDNSCrypt is the DNSCrypt protocol.
	ProtoDNSCrypt Proto = "dnscrypt"
)

Proto values.

type Proxy

type Proxy struct {

	// Config is the proxy configuration.
	//
	// TODO(a.garipov): Remove this embed and create a proper initializer.
	Config

	// RWMutex protects the whole proxy.
	//
	// TODO(e.burkov):  Find out what exactly it protects and name it properly.
	// Also make it a pointer.
	sync.RWMutex
	// contains filtered or unexported fields
}

Proxy combines the proxy server state and configuration.

TODO(a.garipov): Consider extracting conf blocks for better fieldalignment.

func New

func New(c *Config) (p *Proxy, err error)

New creates a new Proxy with the specified configuration. c must not be nil.

TODO(e.burkov): Cover with tests.

TODO(e.burkov): Add context.

func (*Proxy) Addr

func (p *Proxy) Addr(proto Proto) (addr net.Addr)

Addr returns the first listen address for the specified proto or nil if the proxy does not listen to it. proto must be one of Proto: ProtoTCP, ProtoUDP, ProtoTLS, ProtoHTTPS, ProtoQUIC, or ProtoDNSCrypt.

func (*Proxy) Addrs

func (p *Proxy) Addrs(proto Proto) (addrs []net.Addr)

Addrs returns all listen addresses for the specified proto or nil if the proxy does not listen to it. proto must be one of Proto: ProtoTCP, ProtoUDP, ProtoTLS, ProtoHTTPS, ProtoQUIC, or ProtoDNSCrypt.

func (*Proxy) ClearCache

func (p *Proxy) ClearCache()

ClearCache clears the DNS cache of p.

func (*Proxy) LookupNetIP

func (p *Proxy) LookupNetIP(
	ctx context.Context,
	_ string,
	host string,
) (addrs []netip.Addr, err error)

LookupNetIP implements the upstream.Resolver interface for *Proxy. It resolves the specified host IP addresses by sending two DNS queries (A and AAAA) in parallel. It returns both results for those two queries.

func (*Proxy) Resolve

func (p *Proxy) Resolve(ctx context.Context, dctx *DNSContext) (err error)

Resolve is the default resolving method used by the DNS proxy to query upstream servers. It expects dctx is filled with the client's request.

func (*Proxy) ServeHTTP

func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP is the http.Handler implementation that handles DoH queries.

Here is what it returns:

  • http.StatusNotFound if the request is not encrypted and proxy is not configured to accept unencrypted requests,
  • http.StatusBadRequest if there is no DNS request data,
  • http.StatusUnsupportedMediaType if request content type is not "application/dns-message",
  • http.StatusMethodNotAllowed if request method is not GET or POST.

func (*Proxy) Shutdown

func (p *Proxy) Shutdown(ctx context.Context) (err error)

Shutdown implements the service.Interface for *Proxy. It also closes the configured upstream configurations.

func (*Proxy) Start

func (p *Proxy) Start(ctx context.Context) (err error)

Start implements the service.Interface for *Proxy.

type QueryStatistics

type QueryStatistics struct {
	// contains filtered or unexported fields
}

QueryStatistics contains the DNS query statistics for both the upstream and fallback DNS servers.

TODO(e.burkov): Consider adding Clone method.

func (*QueryStatistics) Fallback

func (s *QueryStatistics) Fallback() (us []*UpstreamStatistics)

Fallback returns the DNS query statistics for the fallback DNS servers. us and its items must not be modified.

func (*QueryStatistics) Main

func (s *QueryStatistics) Main() (us []*UpstreamStatistics)

Main returns the DNS query statistics for the upstream DNS servers. us and its items must not be modified.

type UpstreamConfig

type UpstreamConfig struct {
	// DomainReservedUpstreams maps the domains to the upstreams.
	DomainReservedUpstreams map[string][]upstream.Upstream

	// SpecifiedDomainUpstreams maps the specific domain names to the upstreams.
	SpecifiedDomainUpstreams map[string][]upstream.Upstream

	// SubdomainExclusions is set of domains with subdomains exclusions.
	SubdomainExclusions *container.MapSet[string]

	// Upstreams is a list of default upstreams.
	Upstreams []upstream.Upstream
}

UpstreamConfig maps domain names to upstreams.

func ParseUpstreamsConfig

func ParseUpstreamsConfig(
	lines []string,
	opts *upstream.Options,
) (conf *UpstreamConfig, err error)

ParseUpstreamsConfig returns an UpstreamConfig and nil error if the upstream configuration is valid. Otherwise returns a partially filled UpstreamConfig and wrapped error containing lines with errors. It also skips empty lines and comments (lines starting with "#").

Simple upstreams

Single upstream per line. For example:

1.2.3.4
3.4.5.6

Domain specific upstreams

  • reserved upstreams: [/domain1/../domainN/]<upstreamString>
  • subdomains only upstreams: [/*.domain1/../*.domainN]<upstreamString>

Where <upstreamString> is one or many upstreams separated by space (e.g. `1.1.1.1` or `1.1.1.1 2.2.2.2`).

More specific domains take priority over less specific domains. To exclude more specific domains from reserved upstreams querying you should use the following syntax:

[/domain1/../domainN/]#

So the following config:

[/host.com/]1.2.3.4
[/www.host.com/]2.3.4.5"
[/maps.host.com/news.host.com/]#
3.4.5.6

will send queries for *.host.com to 1.2.3.4. Except for *.www.host.com, which will go to 2.3.4.5. And *.maps.host.com or *.news.host.com, which will go to default server 3.4.5.6 with all other domains.

To exclude top level domain from reserved upstreams querying you could use the following:

'[/*.domain.com/]<upstreamString>'

So the following config:

[/*.domain.com/]1.2.3.4
3.4.5.6

will send queries for all subdomains *.domain.com to 1.2.3.4, but domain.com query will be sent to default server 3.4.5.6 as every other query.

TODO(e.burkov): Consider supporting multiple upstreams in a single line for default upstream syntax.

func (*UpstreamConfig) Close

func (uc *UpstreamConfig) Close() (err error)

Close implements the io.Closer interface for *UpstreamConfig.

type UpstreamMode

type UpstreamMode string

UpstreamMode is an enumeration of upstream mode representations.

TODO(d.kolyshev): Set uint8 as underlying type.

const (
	// UpstreamModeLoadBalance is the default upstream mode.  It balances the
	// upstreams load.
	UpstreamModeLoadBalance UpstreamMode = "load_balance"

	// UpstreamModeParallel makes server to query all configured upstream
	// servers in parallel.
	UpstreamModeParallel UpstreamMode = "parallel"

	// UpstreamModeFastestAddr controls whether the server should respond to A
	// or AAAA requests only with the fastest IP address detected by ICMP
	// response time or TCP connection time.
	UpstreamModeFastestAddr UpstreamMode = "fastest_addr"
)

func (UpstreamMode) MarshalText

func (m UpstreamMode) MarshalText() (text []byte, err error)

MarshalText implements encoding.TextMarshaler interface for UpstreamMode.

func (*UpstreamMode) UnmarshalText

func (m *UpstreamMode) UnmarshalText(b []byte) (err error)

UnmarshalText implements encoding.TextUnmarshaler interface for *UpstreamMode.

type UpstreamStatistics

type UpstreamStatistics struct {
	// Error is the DNS lookup error, if any.
	Error error

	// Address is the address of the upstream DNS resolver.
	//
	// TODO(s.chzhen):  Use [upstream.Upstream] when [cacheItem] starts to
	// contain one.
	Address string

	// QueryDuration is the duration of the successful DNS lookup.
	QueryDuration time.Duration

	// IsCached indicates whether the response was served from a cache.
	IsCached bool
}

UpstreamStatistics contains the DNS query statistics.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL