client

package
v0.0.0-...-75a31e8 Latest Latest
Warning

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

Go to latest
Published: Nov 20, 2024 License: GPL-3.0 Imports: 26 Imported by: 0

Documentation

Overview

Package client contains types and logic dealing with AdGuard Home's DNS clients.

TODO(a.garipov): Expand.

Index

Constants

View Source
const ErrClosed errors.Error = "use of closed address processor"

ErrClosed is returned from [AddressProcessor.Close] if it's closed more than once.

Variables

This section is empty.

Functions

func ValidateClientID

func ValidateClientID(id string) (err error)

ValidateClientID returns an error if id is not a valid ClientID.

TODO(s.chzhen): It's an exact copy of the [dnsforward.ValidateClientID] to avoid the import cycle. Remove it.

Types

type AddressProcessor

type AddressProcessor interface {
	Process(ctx context.Context, ip netip.Addr)
	Close() (err error)
}

AddressProcessor is the interface for types that can process clients.

type AddressUpdater

type AddressUpdater interface {
	// UpdateAddress updates information about an IP address, setting host (if
	// not empty) and WHOIS information (if not nil).
	UpdateAddress(ctx context.Context, ip netip.Addr, host string, info *whois.Info)
}

AddressUpdater is the interface for storages of DNS clients that can update information about them.

TODO(a.garipov): Consider using the actual client storage once it is moved into this package.

type DHCP

type DHCP interface {
	// Leases returns all the DHCP leases.
	Leases() (leases []*dhcpsvc.Lease)

	// HostByIP returns the hostname of the DHCP client with the given IP
	// address.  host will be empty if there is no such client, due to an
	// assumption that a DHCP client must always have a hostname.
	HostByIP(ip netip.Addr) (host string)

	// MACByIP returns the MAC address for the given IP address leased.  It
	// returns nil if there is no such client, due to an assumption that a DHCP
	// client must always have a MAC address.
	MACByIP(ip netip.Addr) (mac net.HardwareAddr)
}

DHCP is an interface for accessing DHCP lease data the Storage needs.

type DefaultAddrProc

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

DefaultAddrProc processes incoming client addresses with rDNS and WHOIS, if configured, and updates that information in a client storage.

func NewDefaultAddrProc

func NewDefaultAddrProc(c *DefaultAddrProcConfig) (p *DefaultAddrProc)

NewDefaultAddrProc returns a new running client address processor. c must not be nil.

func (*DefaultAddrProc) Close

func (p *DefaultAddrProc) Close() (err error)

Close implements the AddressProcessor interface for *DefaultAddrProc.

func (*DefaultAddrProc) Process

func (p *DefaultAddrProc) Process(ctx context.Context, ip netip.Addr)

Process implements the AddressProcessor interface for *DefaultAddrProc.

type DefaultAddrProcConfig

type DefaultAddrProcConfig struct {
	// BaseLogger is used to create loggers with custom prefixes for sources of
	// information about runtime clients.  It must not be nil.
	BaseLogger *slog.Logger

	// DialContext is used to create TCP connections to WHOIS servers.
	// DialContext must not be nil if [DefaultAddrProcConfig.UseWHOIS] is true.
	DialContext aghnet.DialContextFunc

	// Exchanger is used to perform rDNS queries.  Exchanger must not be nil if
	// [DefaultAddrProcConfig.UseRDNS] is true.
	Exchanger rdns.Exchanger

	// PrivateSubnets are used to determine if an incoming IP address is
	// private.  It must not be nil.
	PrivateSubnets netutil.SubnetSet

	// AddressUpdater is used to update the information about a client's IP
	// address.  It must not be nil.
	AddressUpdater AddressUpdater

	// InitialAddresses are the addresses that are queued for processing
	// immediately by [NewDefaultAddrProc].
	InitialAddresses []netip.Addr

	// CatchPanics, if true, makes the address processor catch and log panics.
	//
	// TODO(a.garipov): Consider better ways to do this or apply this method to
	// other parts of the codebase.
	CatchPanics bool

	// UseRDNS, if true, enables resolving of client IP addresses using reverse
	// DNS.
	UseRDNS bool

	// UsePrivateRDNS, if true, enables resolving of private client IP addresses
	// using reverse DNS.  See [DefaultAddrProcConfig.PrivateSubnets].
	UsePrivateRDNS bool

	// UseWHOIS, if true, enables resolving of client IP addresses using WHOIS.
	UseWHOIS bool
}

DefaultAddrProcConfig is the configuration structure for address processors.

type EmptyAddrProc

type EmptyAddrProc struct{}

EmptyAddrProc is an AddressProcessor that does nothing.

func (EmptyAddrProc) Close

func (EmptyAddrProc) Close() (_ error)

Close implements the AddressProcessor interface for EmptyAddrProc.

func (EmptyAddrProc) Process

func (EmptyAddrProc) Process(_ context.Context, _ netip.Addr)

Process implements the AddressProcessor interface for EmptyAddrProc.

type EmptyDHCP

type EmptyDHCP struct{}

EmptyDHCP is the empty DHCP implementation that does nothing.

func (EmptyDHCP) HostByIP

func (EmptyDHCP) HostByIP(_ netip.Addr) (host string)

HostByIP implements the DHCP interface for emptyDHCP.

func (EmptyDHCP) Leases

func (EmptyDHCP) Leases() (leases []*dhcpsvc.Lease)

Leases implements the DHCP interface for emptyDHCP.

func (EmptyDHCP) MACByIP

func (EmptyDHCP) MACByIP(_ netip.Addr) (mac net.HardwareAddr)

MACByIP implements the DHCP interface for emptyDHCP.

type HostsContainer

type HostsContainer interface {
	Upd() (updates <-chan *hostsfile.DefaultStorage)
}

HostsContainer is an interface for receiving updates to the system hosts file.

type Persistent

type Persistent struct {
	// UpstreamConfig is the custom upstream configuration for this client.  If
	// it's nil, it has not been initialized yet.  If it's non-nil and empty,
	// there are no valid upstreams.  If it's non-nil and non-empty, these
	// upstream must be used.
	UpstreamConfig *proxy.CustomUpstreamConfig

	// SafeSearch handles search engine hosts rewrites.
	SafeSearch filtering.SafeSearch

	// BlockedServices is the configuration of blocked services of a client.  It
	// must not be nil after initialization.
	BlockedServices *filtering.BlockedServices

	// Name of the persistent client.  Must not be empty.
	Name string

	// Tags is a list of client tags that categorize the client.
	Tags []string

	// Upstreams is a list of custom upstream DNS servers for the client.
	Upstreams []string

	// IPs is a list of IP addresses that identify the client.  The client must
	// have at least one ID (IP, subnet, MAC, or ClientID).
	IPs []netip.Addr

	// Subnets identifying the client.  The client must have at least one ID
	// (IP, subnet, MAC, or ClientID).
	//
	// TODO(s.chzhen):  Use netutil.Prefix.
	Subnets []netip.Prefix

	// MACs identifying the client.  The client must have at least one ID (IP,
	// subnet, MAC, or ClientID).
	MACs []net.HardwareAddr

	// ClientIDs identifying the client.  The client must have at least one ID
	// (IP, subnet, MAC, or ClientID).
	ClientIDs []string

	// UID is the unique identifier of the persistent client.
	UID UID

	// UpstreamsCacheSize is the cache size for custom upstreams.
	UpstreamsCacheSize uint32

	// UpstreamsCacheEnabled specifies whether custom upstreams are used.
	UpstreamsCacheEnabled bool

	// UseOwnSettings specifies whether custom filtering settings are used.
	UseOwnSettings bool

	// FilteringEnabled specifies whether filtering is enabled.
	FilteringEnabled bool

	// SafeBrowsingEnabled specifies whether safe browsing is enabled.
	SafeBrowsingEnabled bool

	// ParentalEnabled specifies whether parental control is enabled.
	ParentalEnabled bool

	// UseOwnBlockedServices specifies whether custom services are blocked.
	UseOwnBlockedServices bool

	// IgnoreQueryLog specifies whether the client requests are logged.
	IgnoreQueryLog bool

	// IgnoreStatistics  specifies whether the client requests are counted.
	IgnoreStatistics bool

	// SafeSearchConf is the safe search filtering configuration.
	//
	// TODO(d.kolyshev): Make SafeSearchConf a pointer.
	SafeSearchConf filtering.SafeSearchConfig
}

Persistent contains information about persistent clients.

func (*Persistent) CloseUpstreams

func (c *Persistent) CloseUpstreams() (err error)

CloseUpstreams closes the client-specific upstream config of c if any.

func (*Persistent) EqualIDs

func (c *Persistent) EqualIDs(prev *Persistent) (equal bool)

EqualIDs returns true if the ids of the current and previous clients are the same.

func (*Persistent) IDs

func (c *Persistent) IDs() (ids []string)

IDs returns a list of client IDs containing at least one element.

func (*Persistent) IDsLen

func (c *Persistent) IDsLen() (n int)

IDsLen returns a length of client ids.

func (*Persistent) SetIDs

func (c *Persistent) SetIDs(ids []string) (err error)

SetIDs parses a list of strings into typed fields and returns an error if there is one.

func (*Persistent) ShallowClone

func (c *Persistent) ShallowClone() (clone *Persistent)

ShallowClone returns a deep copy of the client, except upstreamConfig, safeSearchConf, SafeSearch fields, because it's difficult to copy them.

type Runtime

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

Runtime is a client information from different sources.

func NewRuntime

func NewRuntime(ip netip.Addr) (r *Runtime)

NewRuntime constructs a new runtime client. ip must be valid IP address.

TODO(s.chzhen): Validate IP address.

func (*Runtime) Addr

func (r *Runtime) Addr() (ip netip.Addr)

Addr returns an IP address of the client.

func (*Runtime) Info

func (r *Runtime) Info() (cs Source, host string)

Info returns a client information from the highest-priority source.

func (*Runtime) WHOIS

func (r *Runtime) WHOIS() (info *whois.Info)

WHOIS returns a copy of WHOIS client information.

type Source

type Source uint8

Source represents the source from which the information about the client has been obtained.

const (
	SourceWHOIS Source = iota + 1
	SourceARP
	SourceRDNS
	SourceDHCP
	SourceHostsFile
	SourcePersistent
)

Clients information sources. The order determines the priority.

func (Source) MarshalText

func (cs Source) MarshalText() (text []byte, err error)

MarshalText implements encoding.TextMarshaler for the Source.

func (Source) String

func (cs Source) String() (s string)

String returns a human-readable name of cs.

type Storage

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

Storage contains information about persistent and runtime clients.

func NewStorage

func NewStorage(ctx context.Context, conf *StorageConfig) (s *Storage, err error)

NewStorage returns initialized client storage. conf must not be nil.

func (*Storage) Add

func (s *Storage) Add(ctx context.Context, p *Persistent) (err error)

Add stores persistent client information or returns an error.

func (*Storage) AllowedTags

func (s *Storage) AllowedTags() (tags []string)

AllowedTags returns the list of available client tags. tags must not be modified.

func (*Storage) ClientRuntime

func (s *Storage) ClientRuntime(ip netip.Addr) (rc *Runtime)

ClientRuntime returns a copy of the saved runtime client by ip. If no such client exists, returns nil.

func (*Storage) Find

func (s *Storage) Find(id string) (p *Persistent, ok bool)

Find finds persistent client by string representation of the client ID, IP address, or MAC. And returns its shallow copy.

TODO(s.chzhen): Accept ClientIDData structure instead, which will contain the parsed IP address, if any.

func (*Storage) FindByMAC

func (s *Storage) FindByMAC(mac net.HardwareAddr) (p *Persistent, ok bool)

FindByMAC finds persistent client by MAC and returns its shallow copy. s.mu is expected to be locked.

func (*Storage) FindByName

func (s *Storage) FindByName(name string) (p *Persistent, ok bool)

FindByName finds persistent client by name. And returns its shallow copy.

func (*Storage) FindLoose

func (s *Storage) FindLoose(ip netip.Addr, id string) (p *Persistent, ok bool)

FindLoose is like Storage.Find but it also tries to find a persistent client by IP address without zone. It strips the IPv6 zone index from the stored IP addresses before comparing, because querylog entries don't have it. See TODO on [querylog.logEntry.IP].

Note that multiple clients can have the same IP address with different zones. Therefore, the result of this method is indeterminate.

func (*Storage) RangeByName

func (s *Storage) RangeByName(f func(c *Persistent) (cont bool))

RangeByName calls f for each persistent client sorted by name, unless cont is false.

func (*Storage) RangeRuntime

func (s *Storage) RangeRuntime(f func(rc *Runtime) (cont bool))

RangeRuntime calls f for each runtime client in an undefined order.

func (*Storage) ReloadARP

func (s *Storage) ReloadARP(ctx context.Context)

ReloadARP reloads runtime clients from ARP, if configured.

func (*Storage) RemoveByName

func (s *Storage) RemoveByName(name string) (ok bool)

RemoveByName removes persistent client information. ok is false if no such client exists by that name.

func (*Storage) Shutdown

func (s *Storage) Shutdown(_ context.Context) (err error)

Shutdown gracefully stops the client storage.

TODO(s.chzhen): Pass context.

func (*Storage) Size

func (s *Storage) Size() (n int)

Size returns the number of persistent clients.

func (*Storage) Start

func (s *Storage) Start(ctx context.Context) (err error)

Start starts the goroutines for updating the runtime client information.

TODO(s.chzhen): Pass context.

func (*Storage) Update

func (s *Storage) Update(ctx context.Context, name string, p *Persistent) (err error)

Update finds the stored persistent client by its name and updates its information from p.

func (*Storage) UpdateAddress

func (s *Storage) UpdateAddress(ctx context.Context, ip netip.Addr, host string, info *whois.Info)

UpdateAddress implements the AddressUpdater interface for *Storage

func (*Storage) UpdateDHCP

func (s *Storage) UpdateDHCP(ctx context.Context)

UpdateDHCP updates SourceDHCP runtime client information.

type StorageConfig

type StorageConfig struct {
	// Logger is used for logging the operation of the client storage.  It must
	// not be nil.
	Logger *slog.Logger

	// DHCP is used to match IPs against MACs of persistent clients and update
	// [SourceDHCP] runtime client information.  It must not be nil.
	DHCP DHCP

	// EtcHosts is used to update [SourceHostsFile] runtime client information.
	EtcHosts HostsContainer

	// ARPDB is used to update [SourceARP] runtime client information.
	ARPDB arpdb.Interface

	// InitialClients is a list of persistent clients parsed from the
	// configuration file.  Each client must not be nil.
	InitialClients []*Persistent

	// ARPClientsUpdatePeriod defines how often [SourceARP] runtime client
	// information is updated.
	ARPClientsUpdatePeriod time.Duration

	// RuntimeSourceDHCP specifies whether to update [SourceDHCP] information
	// of runtime clients.
	RuntimeSourceDHCP bool
}

StorageConfig is the client storage configuration structure.

type UID

type UID uuid.UUID

UID is the type for the unique IDs of persistent clients.

func MustNewUID

func MustNewUID() (uid UID)

MustNewUID is a wrapper around NewUID that panics if there is an error.

func NewUID

func NewUID() (uid UID, err error)

NewUID returns a new persistent client UID. Any error returned is an error from the cryptographic randomness reader.

func (UID) MarshalText

func (uid UID) MarshalText() ([]byte, error)

MarshalText implements the encoding.TextMarshaler for UID.

func (*UID) UnmarshalText

func (uid *UID) UnmarshalText(data []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface for UID.

Jump to

Keyboard shortcuts

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