client

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jul 15, 2026 License: Apache-2.0 Imports: 26 Imported by: 0

Documentation

Overview

Package client contains client-related structures and logic.

Index

Constants

View Source
const (
	// SchemeHTTPS is the scheme for DNS-over-HTTPS upstreams.
	SchemeHTTPS = urlutil.SchemeHTTPS

	// SchemeQUIC is the scheme for DNS-over-QUIC upstreams.
	SchemeQUIC = "quic"

	// SchemeTLS is the scheme for DNS-over-TLS upstreams.
	SchemeTLS = "tls"
)

Constants for valid encrypted DNS upstream schemes.

View Source
const (
	// DeviceTypeLen is the length of DeviceType.
	DeviceTypeLen = 3

	// ProfileIDLen is the length of ProfileID.
	ProfileIDLen = 8
)

Constants for upstream templates.

TODO(e.burkov): Consider moving to agdc.

Variables

This section is empty.

Functions

func IsIdentifiable

func IsIdentifiable(addr netip.Addr) (ok bool)

IsIdentifiable returns true if the given address is either a private non-loopback address or a global unicast address. Note, that it may be used as netutil.SubnetSetFunc.

Types

type AutodeviceClientConfig

type AutodeviceClientConfig map[string]*AutodeviceUpstreamConfig

AutodeviceClientConfig is the mapping of question domains to autodevice client configurations. Its keys, if not empty, must be valid non-FQDNs. Its values must be valid.

type AutodeviceUpstreamConfig

type AutodeviceUpstreamConfig struct {
	// UpstreamTemplate is a template for creating upstream configurations for
	// new clients.  It must be valid and have an encrypted DNS protocol scheme,
	// i.e.:
	//  - [SchemeHTTPS]
	//  - [SchemeQUIC]
	//  - [SchemeTLS]
	UpstreamTemplate *url.URL

	// Options are used to create dynamic upstreams.
	Options *upstream.Options

	// DeviceType specifies the type of device that will be created for new
	// clients.  It must be valid.
	DeviceType DeviceType

	// ProfileID specifies the profile to which new clients will be added.  It
	// must be valid.
	ProfileID ProfileID
}

AutodeviceUpstreamConfig defines the configuration for clients that are automatically created on demand.

type Client

type Client interface {
	// Upstreams returns the upstream configuration for the client.  upstreams
	// must not be nil, unless documented otherwise.
	Upstreams() (upstreams *proxy.CustomUpstreamConfig)
}

Client is an interface for DNS clients.

type ConsequentHumanIDSource

type ConsequentHumanIDSource []HumanIDSource

ConsequentHumanIDSource concatenates multiple HumanIDSource instances.

TODO(m.kazantsev): Consider removing this implementation

func (ConsequentHumanIDSource) Identify

func (c ConsequentHumanIDSource) Identify(
	ctx context.Context,
	addr netip.Addr,
) (id *ValidHumanID, err error)

Identify implements the HumanIDSource interface for ConsequentIDSource. If one or more errors are returned from sources of the consequence, they are ignored.

type DefaultHumanIDSource

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

DefaultHumanIDSource is a simple HumanIDSource that generates a HumanID based solely on the given address.

func NewDefaultHumanIDSource

func NewDefaultHumanIDSource(conf *DefaultHumanIDSourceConfig) (hs *DefaultHumanIDSource)

NewDefaultHumanIDSource returns properly initialized *DefaultHumanIDSource. conf must be non-nil and valid.

func (*DefaultHumanIDSource) Identify

func (d *DefaultHumanIDSource) Identify(
	ctx context.Context,
	addr netip.Addr,
) (id *ValidHumanID, err error)

Identify implements the HumanIDSource interface for *DefaultHumanIDSource.

type DefaultHumanIDSourceConfig

type DefaultHumanIDSourceConfig struct {
	// Clock is used for determining the validity of IDs.  It must not be nil.
	Clock timeutil.Clock

	// ValidityIvl is a time interval of validity.
	ValidityIvl time.Duration
}

DefaultHumanIDSourceConfig is the configuration for DefaultHumanIDSource.

type DefaultStorage

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

DefaultStorage is a default implementation of the Storage interface.

func NewDefaultStorage

func NewDefaultStorage(c *DefaultStorageConfig) (s *DefaultStorage)

NewDefaultStorage creates a new properly configured *DefaultStorage. c must be valid.

func (*DefaultStorage) Get

func (d *DefaultStorage) Get(
	ctx context.Context,
	addr netip.Addr,
	questionDomain string,
) (c Client, ok bool)

Get implements the Storage interface for *DefaultStorage.

func (*DefaultStorage) Shutdown

func (d *DefaultStorage) Shutdown(ctx context.Context) (err error)

Shutdown implements the service.Interface interface for *DefaultStorage.

func (*DefaultStorage) Start

func (d *DefaultStorage) Start(ctx context.Context) (err error)

Start implements the service.Interface interface for *DefaultStorage.

type DefaultStorageConfig

type DefaultStorageConfig struct {
	// Logger is used for logging storage operations.  It must not be nil.
	Logger *slog.Logger

	// Static is a mapping of IP prefixes to clients' domain specifications that
	// are known in advance.  Each key, if not empty, and value must be valid.
	// Prefixes must not overlap.
	//
	// TODO(e.burkov):  Consider initializing the upstreams in this package,
	// instead of passing them from the outside.
	Static map[netip.Prefix]StaticClientConfig

	// HumanIDSource is used to identify dynamically created clients.  It must
	// not be nil, use [EmptyHumanIDSource] if no identification is needed.
	HumanIDSource HumanIDSource

	// UpstreamConstructor is used to construct upstreams from addresses.  It
	// must not be nil.
	UpstreamConstructor UpstreamConstructor

	// Identifiable defines the filter for addresses that should be identified
	// and turned into autodevice clients.  If Autodevice is not empty, it must
	// not be nil, use [IsIdentifiable] wrapped in [netutil.SubnetSetFunc] as a
	// sensible default.
	Identifiable netutil.SubnetSet

	// Autodevice is a mapping of IP prefixes to configurations of clients that
	// should be created automatically on demand.  Empty prefix defines a
	// default configuration for all addresses that are not covered by other
	// prefixes, all of which must be valid and must not overlap.  Each value
	// must be valid.
	Autodevice map[netip.Prefix]AutodeviceClientConfig

	// Clock is used to get the current time and run timers.  It must not be
	// nil.
	Clock timeutil.ClockAfter

	// CleanupIvl is the interval at which expired clients are cleaned up.  It
	// must be positive if Autodevice is not empty.
	CleanupIvl time.Duration

	// CacheEnabled controls whether dynamically created custom upstream configs
	// get their own cache.
	CacheEnabled bool

	// CacheSize is the size of the dynamically created custom upstream cache.
	// It must be positive if CacheEnabled is true.
	CacheSize int
}

DefaultStorageConfig is a configuration structure for DefaultStorage.

type DefaultUpstreamConstructor

type DefaultUpstreamConstructor struct{}

DefaultUpstreamConstructor is a default implementation of UpstreamConstructor that uses upstream.AddressToUpstream to construct upstreams.

func (DefaultUpstreamConstructor) AddressToUpstream

func (DefaultUpstreamConstructor) AddressToUpstream(
	addr string,
	opts *upstream.Options,
) (u upstream.Upstream, err error)

AddressToUpstream implements the UpstreamConstructor interface for DefaultUpstreamConstructor.

type DeviceType

type DeviceType string

DeviceType is a type of a device.

TODO(e.burkov): Consider moving to agdc.

func NewDeviceType

func NewDeviceType(s string) (dt DeviceType, err error)

NewDeviceType converts s into a DeviceType and makes sure that it's valid.

type EmptyHumanIDSource

type EmptyHumanIDSource struct{}

EmptyHumanIDSource is an empty HumanIDSource.

func (EmptyHumanIDSource) Identify

func (EmptyHumanIDSource) Identify(_ context.Context, _ netip.Addr) (id *ValidHumanID, err error)

Identify implements the HumanIDSource interface for EmptyHumanIDSource. It always returns a nil id and errors.ErrNoValue.

type EmptyStorage

type EmptyStorage struct {
	service.Empty
}

EmptyStorage is an implementation of Storage that does nothing.

func (EmptyStorage) Get

func (EmptyStorage) Get(_ context.Context, _ netip.Addr, _ string) (c Client, ok bool)

Get implements the Storage interface for EmptyStorage. It always returns nil and false.

type HumanID

type HumanID string

HumanID is an identifier for DNS client. It must be unique for each client among a single Storage.

type HumanIDSource

type HumanIDSource interface {
	// Identify returns an identification info for a client with the given
	// address.  If there is no error, id must not be nil.  addr must be a valid
	// unmapped global unicast or private IP.  Identify must not be called
	// concurrently for the same addr.
	Identify(ctx context.Context, addr netip.Addr) (id *ValidHumanID, err error)
}

HumanIDSource is an interface for retrieving clients' identifiers by their address.

type ProfileID

type ProfileID string

ProfileID is the ID of a profile.

TODO(e.burkov): Consider moving to agdc.

func NewProfileID

func NewProfileID(s string) (id ProfileID, err error)

NewProfileID converts s into a ProfileID and makes sure that it's valid.

NOTE: Keep in sync with https://github.com/AdguardTeam/AdGuardDNS/blob/3f26cca7e094801647ea6e93503d6ed61c545737/internal/agd/profile.go#L114.

type RDNSIDSource

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

RDNSIDSource is an HumanIDSource that assigns HumanIDs based on the hostname obtained from reverse DNS lookups of IP addresses.

func NewRDNSIDSource

func NewRDNSIDSource(conf *RDNSIDSourceConfig) (r *RDNSIDSource)

NewRDNSIDSource returns properly initialized *RDNSIDSource. conf must be non-nil and valid.

func (*RDNSIDSource) Identify

func (r *RDNSIDSource) Identify(
	ctx context.Context,
	addr netip.Addr,
) (id *ValidHumanID, err error)

Identify implements the HumanIDSource interface for *RDNSIDSource. ctx must contain logger accessible with slogutil.LoggerFromContext.

type RDNSIDSourceConfig

type RDNSIDSourceConfig struct {
	// Clock is used for determining the validity of IDs.  It must not be nil.
	Clock timeutil.Clock

	// UpstreamConfig is the configuration for the upstream resolver used for
	// reverse DNS lookups.  It must be valid according to
	// [proxy.UpstreamConfig.ValidatePrivate].
	UpstreamConfig *proxy.UpstreamConfig
}

RDNSIDSourceConfig is the configuration for RDNSIDSource.

type StaticClient

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

StaticClient is a Client implementation that returns a static upstream config.

func NewStaticClient

func NewStaticClient(upstreams *proxy.CustomUpstreamConfig) (sc *StaticClient)

NewStaticClient creates a new properly initialized StaticClient. conf must be valid.

func (*StaticClient) Upstreams

func (s *StaticClient) Upstreams() (upstreams *proxy.CustomUpstreamConfig)

Upstreams implements the Client interface for *StaticClient.

type StaticClientConfig

type StaticClientConfig map[string]*StaticClient

StaticClientConfig is a mapping of domain names to static clients. Its keys, if not empty, must be valid non-FQDNs. Its values must be valid.

type Storage

type Storage interface {
	// Get returns the client for addr and questionDomain.  addr must be valid
	// and must not be mapped.  questionDomain must be valid non-FQDN in lower
	// case.
	//
	// c must not be nil if ok is true.  It must be safe for concurrent use.
	Get(ctx context.Context, addr netip.Addr, questionDomain string) (c Client, ok bool)

	// Interface is used to start necessary background routines and release the
	// resources after shutdown.
	service.Interface
}

Storage is an interface for storing clients.

type UpstreamConstructor

type UpstreamConstructor interface {
	// AddressToUpstream constructs an upstream from the given address and
	// options.  If opts is nil, the default options are used.
	//
	// See [upstream.AddressToUpstream].
	AddressToUpstream(addr string, opts *upstream.Options) (u upstream.Upstream, err error)
}

UpstreamConstructor is an interface for constructing upstreams from addresses. Its only purpose is to simplify testing of DefaultStorage.

type ValidHumanID

type ValidHumanID struct {
	// Until is the time until which ID is valid.  It must not be empty.
	Until time.Time

	// ID is the identifier for a client.  It must be valid for at least until
	// Until.
	ID HumanID
}

ValidHumanID is a HumanID that is valid until a certain time.

Jump to

Keyboard shortcuts

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