v1.4.8 Latest Latest

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

Go to latest
Published: Sep 27, 2023 License: AGPL-3.0 Imports: 34 Imported by: 3



Package resolver is responsible for querying DNS.

DNS Servers

Internal lists of resolvers to use are built on start and rebuilt on every config or network change. Configured DNS servers are prioritized over servers assigned by dhcp. Domain and search options (here referred to as "search scopes") are being considered.


Usage of DNS Servers can be regulated using the configuration:

DoNotUseAssignedDNS        // Do not use DNS servers assigned by DHCP
DoNotUseMDNS               // Do not use mDNS
DoNotForwardSpecialDomains // Do not forward special domains to local resolvers, except if they have a search scope for it

Note: The DHCP options "domain" and "search" are ignored for servers assigned by DHCP that do not reside within local address space.

Resolving DNS

Various different queries require the resolver to behave in different manner:

Queries for "localhost." are immediately responded with and ::1, for A and AAAA queries and NXDomain for others. Reverse lookups on local address ranges (10/8, 172.16/12, 192.168/16, fe80::/7) will be tried against every local resolver and finally mDNS until a successful, non-NXDomain answer is received. Special domains ("example.", "", "", "", "invalid.", "test.", "onion.") are resolved using search scopes and local resolvers. All other domains are resolved using search scopes and all available resolvers.



View Source
const (
	BlockDetectionRefused     = "refused"
	BlockDetectionZeroIP      = "zeroip"
	BlockDetectionEmptyAnswer = "empty"
	BlockDetectionDisabled    = "disabled"

Supported upstream block detections.

View Source
const (
	ServerTypeDNS  = "dns"
	ServerTypeTCP  = "tcp"
	ServerTypeDoT  = "dot"
	ServerTypeDoH  = "doh"
	ServerTypeMDNS = "mdns"
	ServerTypeEnv  = "env"

	ServerSourceConfigured      = "config"
	ServerSourceOperatingSystem = "system"
	ServerSourceMDNS            = "mdns"
	ServerSourceEnv             = "env"

DNS Resolver Attributes.

View Source
const (
	HTTPSProtocol = "https"
	TLSProtocol   = "tls"

DNS resolver scheme aliases.

View Source
const (
	DNSClassMulticast = dns.ClassINET | 1<<15

DNS Classes.

View Source
const (
	// IPInfoProfileScopeGlobal is the profile scope used for unscoped IPInfo entries.
	IPInfoProfileScopeGlobal = "global"
View Source
const (
	// InternalSpecialUseDomain is the domain scope used for internal services.
	InternalSpecialUseDomain = ""


View Source
var (
	CompatDNSCheckInternalDomainScope string
	CompatSelfCheckIsFailing          func() bool
	CompatSubmitDNSCheckDomain        func(subdomain string) (respondWith net.IP)

This is a workaround for enabling the resolver to work with the compat module without importing it. Long-term, the network module should not import the resolver package, as this breaks the SPN hub.

View Source
var (
	CfgOptionNameServersKey = "dns/nameservers"

	CfgOptionNoAssignedNameserversKey = "dns/noAssignedNameservers"

	CfgOptionUseStaleCacheKey = "dns/useStaleCache"

	CfgOptionNoMulticastDNSKey = "dns/noMulticastDNS"

	CfgOptionNoInsecureProtocolsKey = "dns/noInsecureProtocols"

	CfgOptionDontResolveSpecialDomainsKey = "dns/dontResolveSpecialDomains"

	CfgOptionNameserverRetryRateKey = "dns/nameserverRetryRate"

Configuration Keys.

View Source
var (

	// ErrNotFound is a basic error that will match all "not found" errors.
	ErrNotFound = errors.New("record could not be found")
	// ErrBlocked is basic error that will match all "blocked" errors.
	ErrBlocked = errors.New("query was blocked")
	// ErrLocalhost is returned to *.localhost queries.
	ErrLocalhost = errors.New("query for localhost")
	// ErrTimeout is returned when a query times out.
	ErrTimeout = errors.New("query timed out")
	// ErrOffline is returned when no network connection is detected.
	ErrOffline = errors.New("device is offine")
	// ErrFailure is returned when the type of failure is unclear.
	ErrFailure = errors.New("query failed")
	// ErrContinue is returned when the resolver has no answer, and the next resolver should be asked.
	ErrContinue = errors.New("resolver has no answer")
	// ErrShuttingDown is returned when the resolver is shutting down.
	ErrShuttingDown = errors.New("resolver is shutting down")

	// ErrTestDomainsDisabled wraps ErrBlocked.
	ErrTestDomainsDisabled = fmt.Errorf("%w: test domains disabled", ErrBlocked)
	// ErrSpecialDomainsDisabled wraps ErrBlocked.
	ErrSpecialDomainsDisabled = fmt.Errorf("%w: special domains disabled", ErrBlocked)
	// ErrInvalid wraps ErrNotFound.
	ErrInvalid = fmt.Errorf("%w: invalid request", ErrNotFound)
	// ErrNoCompliance wraps ErrBlocked and is returned when no resolvers were able to comply with the current settings.
	ErrNoCompliance = fmt.Errorf("%w: no compliant resolvers for this query", ErrBlocked)


View Source
var FailThreshold = 20

FailThreshold is amount of errors a resolvers must experience in order to be regarded as failed.


func AddToDebugInfo added in v0.7.11

func AddToDebugInfo(di *debug.Info)

AddToDebugInfo adds the system status to the given debug.Info.

func ForceResolverReconnect added in v1.0.6

func ForceResolverReconnect(ctx context.Context)

ForceResolverReconnect forces all resolvers to reconnect.

func IsResolverAddress added in v0.7.3

func IsResolverAddress(ip net.IP, port uint16) bool

IsResolverAddress returns whether the given ip and port match a configured resolver.

func ResetCachedRecord added in v0.6.5

func ResetCachedRecord(domain, question string) error

ResetCachedRecord deletes a NameRecord from the cache database.

func ResolveIPAndValidate

func ResolveIPAndValidate(ctx context.Context, ip string, securityLevel uint8) (domain string, err error)

ResolveIPAndValidate finds (reverse DNS), validates (forward DNS) and returns the domain name assigned to the given IP.

func SetLocalAddrFactory

func SetLocalAddrFactory(laf func(network string) net.Addr)

SetLocalAddrFactory supplies the intel package with a function to get permitted local addresses for connections.


type BasicResolverConn

type BasicResolverConn struct {
	sync.Mutex // Also used by inheriting structs.
	// contains filtered or unexported fields

BasicResolverConn implements ResolverConn for standard dns clients.

func (*BasicResolverConn) IsFailing added in v0.4.4

func (brc *BasicResolverConn) IsFailing() bool

IsFailing returns if this resolver is currently failing.

func (*BasicResolverConn) ReportFailure added in v0.4.4

func (brc *BasicResolverConn) ReportFailure()

ReportFailure reports that an error occurred with this resolver.

func (*BasicResolverConn) ResetFailure added in v0.6.9

func (brc *BasicResolverConn) ResetFailure()

ResetFailure resets the failure status.

type BlockedUpstreamError added in v0.4.1

type BlockedUpstreamError struct {
	ResolverName string

BlockedUpstreamError is returned when a DNS request has been blocked by the upstream server.

func (*BlockedUpstreamError) Error added in v0.4.1

func (blocked *BlockedUpstreamError) Error() string

func (*BlockedUpstreamError) Unwrap added in v0.4.1

func (blocked *BlockedUpstreamError) Unwrap() error

Unwrap implements errors.Unwrapper.

type DNSRequestContext added in v0.7.5

type DNSRequestContext struct {
	Domain   string
	Question string
	RCode    string

	ServedFromCache bool
	RequestingNew   bool
	IsBackup        bool
	Filtered        bool

	Modified time.Time
	Expires  time.Time

DNSRequestContext is a static structure to add information to DNS request connections.

type HTTPSQuery added in v0.9.1

type HTTPSQuery struct {
	Query    *Query
	Response chan *dns.Msg

HTTPSQuery holds the query information for a hTTPSResolverConn.

func (*HTTPSQuery) MakeCacheRecord added in v0.9.1

func (tq *HTTPSQuery) MakeCacheRecord(reply *dns.Msg, resolverInfo *ResolverInfo) *RRCache

MakeCacheRecord creates an RRCache record from a reply.

type HTTPSResolver added in v0.9.1

type HTTPSResolver struct {
	// contains filtered or unexported fields

HTTPSResolver is a resolver using just a single tcp connection with pipelining.

func NewHTTPSResolver added in v0.9.1

func NewHTTPSResolver(resolver *Resolver) *HTTPSResolver

NewHTTPSResolver returns a new HTTPSResolver.

func (*HTTPSResolver) ForceReconnect added in v1.0.6

func (hr *HTTPSResolver) ForceReconnect(ctx context.Context)

ForceReconnect forces the resolver to re-establish the connection to the server.

func (*HTTPSResolver) Query added in v0.9.1

func (hr *HTTPSResolver) Query(ctx context.Context, q *Query) (*RRCache, error)

Query executes the given query against the resolver.

type IPInfo

type IPInfo struct {

	// IP holds the actual IP address.
	IP string

	// ProfileID is used to scope this entry to a process group.
	ProfileID string

	// ResolvedDomain is a slice of domains that
	// have been requested by various applications
	// and have been resolved to IP.
	ResolvedDomains ResolvedDomains

IPInfo represents various information about an IP.

func GetIPInfo

func GetIPInfo(profileID, ip string) (*IPInfo, error)

GetIPInfo gets an IPInfo record from the database.

func (*IPInfo) AddDomain

func (info *IPInfo) AddDomain(resolved ResolvedDomain)

AddDomain adds a new resolved domain to IPInfo.

func (*IPInfo) MostRecentDomain added in v0.6.0

func (info *IPInfo) MostRecentDomain() *ResolvedDomain

MostRecentDomain returns the most recent domain.

func (*IPInfo) Save

func (info *IPInfo) Save() error

Save saves the IPInfo record to the database.

func (*IPInfo) String

func (info *IPInfo) String() string

String returns a string consisting of the domains that have seen to use this IP.

type NameRecord

type NameRecord struct {

	Domain   string
	Question string
	RCode    int
	Answer   []string
	Ns       []string
	Extra    []string
	Expires  int64

	Resolver *ResolverInfo

NameRecord is helper struct to RRCache to better save data to the database.

func GetNameRecord

func GetNameRecord(domain, question string) (*NameRecord, error)

GetNameRecord gets a NameRecord from the database.

func (*NameRecord) IsValid added in v0.6.7

func (nameRecord *NameRecord) IsValid() bool

IsValid returns whether the NameRecord is valid and may be used. Otherwise, it should be disregarded.

func (*NameRecord) Save

func (nameRecord *NameRecord) Save() error

Save saves the NameRecord to the database.

type PlainResolver added in v0.4.14

type PlainResolver struct {

PlainResolver is a resolver using plain DNS.

func NewPlainResolver added in v0.4.14

func NewPlainResolver(resolver *Resolver) *PlainResolver

NewPlainResolver returns a new TPCResolver.

func (*PlainResolver) ForceReconnect added in v1.0.6

func (pr *PlainResolver) ForceReconnect(_ context.Context)

ForceReconnect forces the resolver to re-establish the connection to the server. Does nothing for PlainResolver, as every request uses its own connection.

func (*PlainResolver) Query added in v0.4.14

func (pr *PlainResolver) Query(ctx context.Context, q *Query) (*RRCache, error)

Query executes the given query against the resolver.

type Query

type Query struct {
	FQDN               string
	QType              dns.Type
	SecurityLevel      uint8
	NoCaching          bool
	IgnoreFailing      bool
	LocalResolversOnly bool

	// ICANNSpace signifies if the domain is within ICANN managed domain space.
	ICANNSpace bool
	// Domain root is the effective TLD +1.
	DomainRoot string
	// contains filtered or unexported fields

Query describes a dns query.

func (*Query) ID added in v0.4.13

func (q *Query) ID() string

ID returns the ID of the query consisting of the domain and question type.

func (*Query) InitPublicSuffixData added in v0.8.13

func (q *Query) InitPublicSuffixData()

InitPublicSuffixData initializes the public suffix data.

type RRCache

type RRCache struct {
	// Respnse Header
	Domain   string
	Question dns.Type
	RCode    int

	// Response Content
	Answer  []dns.RR `json:"-"`
	Ns      []dns.RR `json:"-"`
	Extra   []dns.RR `json:"-"`
	Expires int64

	// Resolver Information
	Resolver *ResolverInfo `json:"-"`

	// Metadata about the request and handling
	ServedFromCache bool
	RequestingNew   bool
	IsBackup        bool
	Filtered        bool
	FilteredEntries []string

	// Modified holds when this entry was last changed, ie. saved to database.
	// This field is only populated when the entry comes from the cache.
	Modified int64

RRCache is a single-use structure to hold a DNS response. Persistence is handled through NameRecords because of a limitation of the underlying dns library.

func GetRRCache

func GetRRCache(domain string, question dns.Type) (*RRCache, error)

GetRRCache tries to load the corresponding NameRecord from the database and convert it.

func QueryPortmasterEnv added in v0.8.13

func QueryPortmasterEnv(ctx context.Context, q *Query) (*RRCache, error)

QueryPortmasterEnv queries the environment resolver directly.

func Resolve

func Resolve(ctx context.Context, q *Query) (rrCache *RRCache, err error)

Resolve resolves the given query for a domain and type and returns a RRCache object or nil, if the query failed.

func (*RRCache) Cacheable added in v0.5.5

func (rrCache *RRCache) Cacheable() bool

Cacheable returns whether the record should be cached.

func (*RRCache) Clean

func (rrCache *RRCache) Clean(minExpires uint32)

Clean sets all TTLs to 17 and sets cache expiry with specified minimum.

func (*RRCache) Expired

func (rrCache *RRCache) Expired() bool

Expired returns whether the record has expired.

func (*RRCache) ExpiresSoon added in v0.5.5

func (rrCache *RRCache) ExpiresSoon() bool

ExpiresSoon returns whether the record will expire soon (or already has) and should already be refreshed.

func (*RRCache) ExportAllARecords

func (rrCache *RRCache) ExportAllARecords() (ips []net.IP)

ExportAllARecords return of a list of all A and AAAA IP addresses.

func (*RRCache) Flags

func (rrCache *RRCache) Flags() string

Flags formats ServedFromCache and RequestingNew to a condensed, flag-like format.

func (*RRCache) GetExtraRRs added in v0.5.5

func (rrCache *RRCache) GetExtraRRs(ctx context.Context, query *dns.Msg) (extra []dns.RR)

GetExtraRRs returns a slice of RRs with additional informational records.

func (*RRCache) ID added in v0.4.13

func (rrCache *RRCache) ID() string

ID returns the ID of the RRCache consisting of the domain and question type.

func (*RRCache) ReplaceAnswerNames added in v0.5.7

func (rrCache *RRCache) ReplaceAnswerNames(fqdn string)

ReplaceAnswerNames is a helper function that replaces all answer names, that match the query domain, with another value. This is used to support handling non-standard query names, which are resolved normalized, but have to be reverted back for the origin non-standard query name in order for the clients to recognize the response.

func (*RRCache) ReplyWithDNS added in v0.5.5

func (rrCache *RRCache) ReplyWithDNS(ctx context.Context, request *dns.Msg) *dns.Msg

ReplyWithDNS creates a new reply to the given query with the data from the RRCache, and additional informational records.

func (*RRCache) Save

func (rrCache *RRCache) Save() error

Save saves the RRCache to the database as a NameRecord.

func (*RRCache) ShallowCopy

func (rrCache *RRCache) ShallowCopy() *RRCache

ShallowCopy returns a shallow copy of the cache. slices are not copied, but referenced.

func (*RRCache) ToDNSRequestContext added in v0.7.5

func (rrCache *RRCache) ToDNSRequestContext() *DNSRequestContext

ToDNSRequestContext returns a new DNSRequestContext of the RRCache.

func (*RRCache) ToNameRecord

func (rrCache *RRCache) ToNameRecord() *NameRecord

ToNameRecord converts the RRCache to a NameRecord for cleaner persistence.

type ResolvedDomain added in v0.4.1

type ResolvedDomain struct {
	// Domain is the domain as requested by the application.
	Domain string

	// CNAMEs is a list of CNAMEs that have been resolved for
	// Domain.
	CNAMEs []string

	// Resolver holds basic information about the resolver that provided this
	// information.
	Resolver *ResolverInfo

	// DNSRequestContext holds the DNS request context.
	DNSRequestContext *DNSRequestContext

	// Expires holds the timestamp when this entry expires.
	// This does not mean that the entry may not be used anymore afterwards,
	// but that this is used to calcuate the TTL of the database record.
	Expires int64

ResolvedDomain holds a Domain name and a list of CNAMES that have been resolved.

func (*ResolvedDomain) String added in v0.4.1

func (resolved *ResolvedDomain) String() string

String returns a string representation of ResolvedDomain including the CNAME chain. It implements fmt.Stringer.

type ResolvedDomains added in v0.4.1

type ResolvedDomains []ResolvedDomain

ResolvedDomains is a helper type for operating on a slice of ResolvedDomain.

func (ResolvedDomains) String added in v0.4.1

func (rds ResolvedDomains) String() string

String returns a string representation of all domains joined to a single string.

type Resolver

type Resolver struct {
	// Server config url (and ID)
	// Supported parameters:
	// - `verify=domain`: verify domain (dot only)
	// - `name=name`: human readable name for resolver
	// - `blockedif=empty`: how to detect if the dns service blocked something
	//	- `empty`: NXDomain result, but without any other record in any section
	//  - `refused`: Request was refused
	//	- `zeroip`: Answer only contains zeroip
	ConfigURL string

	// Info holds the parsed configuration.
	Info *ResolverInfo

	// ServerAddress holds the resolver address for easier use.
	ServerAddress string

	// UpstreamBlockDetection defines the detection type
	// to identifier upstream DNS query blocking.
	// Valid values are:
	//	 - zeroip
	//	 - empty
	//   - refused (default)
	//	 - disabled
	UpstreamBlockDetection string

	// Special Options
	Search     []string
	SearchOnly bool
	Path       string

	// logic interface
	Conn ResolverConn `json:"-"`

Resolver holds information about an active resolver.

func GetResolversInScope

func GetResolversInScope(ctx context.Context, q *Query) (selected []*Resolver, primarySource string, tryAll bool)

GetResolversInScope returns all resolvers that are in scope the resolve the given query and options.

func (*Resolver) IsBlockedUpstream added in v0.4.1

func (resolver *Resolver) IsBlockedUpstream(answer *dns.Msg) bool

IsBlockedUpstream returns true if the request has been blocked upstream.

func (*Resolver) String

func (resolver *Resolver) String() string

String returns the URL representation of the resolver.

type ResolverConn

type ResolverConn interface {
	Query(ctx context.Context, q *Query) (*RRCache, error)
	IsFailing() bool
	ForceReconnect(ctx context.Context)

ResolverConn is an interface to implement different types of query backends.

type ResolverInfo added in v0.6.7

type ResolverInfo struct {
	// Name describes the name given to the resolver. The name is configured in the config URL using the name parameter.
	Name string

	// Type describes the type of the resolver.
	// Possible values include dns, tcp, dot, doh, mdns, env.
	Type string

	// Source describes where the resolver configuration came from.
	// Possible values include config, system, mdns, env.
	Source string

	// IP is the IP address of the resolver
	IP net.IP

	// Domain of the dns server if it has one
	Domain string

	// IPScope is the network scope of the IP address.
	IPScope netutils.IPScope

	// Port is the udp/tcp port of the resolver.
	Port uint16
	// contains filtered or unexported fields

ResolverInfo is a subset of resolver attributes that is attached to answers from that server in order to use it later for decision making. It must not be changed by anyone after creation and initialization is complete.

func (*ResolverInfo) Copy added in v0.6.7

func (info *ResolverInfo) Copy() *ResolverInfo

Copy returns a full copy of the ResolverInfo.

func (*ResolverInfo) DescriptiveName added in v0.6.7

func (info *ResolverInfo) DescriptiveName() string

DescriptiveName returns a human readable, but also detailed representation of the resolver.

func (*ResolverInfo) ID added in v0.6.7

func (info *ResolverInfo) ID() string

ID returns the unique ID of the resolver.

type Scope

type Scope struct {
	Domain    string
	Resolvers []*Resolver

Scope defines a domain scope and which resolvers can resolve it.

type TCPResolver added in v0.4.9

type TCPResolver struct {
	// contains filtered or unexported fields

TCPResolver is a resolver using just a single tcp connection with pipelining.

func NewTCPResolver added in v0.4.9

func NewTCPResolver(resolver *Resolver) *TCPResolver

NewTCPResolver returns a new TPCResolver.

func (*TCPResolver) ForceReconnect added in v1.0.6

func (tr *TCPResolver) ForceReconnect(ctx context.Context)

ForceReconnect forces the resolver to re-establish the connection to the server.

func (*TCPResolver) Query added in v0.4.9

func (tr *TCPResolver) Query(ctx context.Context, q *Query) (*RRCache, error)

Query executes the given query against the resolver.

func (*TCPResolver) UseTLS added in v0.4.9

func (tr *TCPResolver) UseTLS() *TCPResolver

UseTLS enabled TLS for the TCPResolver. TLS settings must be correctly configured in the Resolver.

Jump to

Keyboard shortcuts

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