addrmgr

package module
v2.0.2 Latest Latest
Warning

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

Go to latest
Published: Jun 7, 2023 License: ISC Imports: 19 Imported by: 16

Documentation

Overview

Package addrmgr implements concurrency safe Decred address manager.

Address Manager Overview

In order maintain the peer-to-peer Decred network, there needs to be a source of addresses to connect to as nodes come and go. The Decred protocol provides the getaddr and addr messages to allow peers to communicate known addresses with each other. However, there needs to a mechanism to store those results and select peers from them. It is also important to note that remote peers can't be trusted to send valid peers nor attempt to provide you with only peers they control with malicious intent.

With that in mind, this package provides a concurrency safe address manager for caching and selecting peers in a non-deterministic manner. The general idea is the caller adds addresses to the address manager and notifies it when addresses are connected, known good, and attempted. The caller also requests addresses as it needs them.

The address manager internally segregates the addresses into groups and non-deterministically selects groups in a cryptographically random manner. This reduce the chances multiple addresses from the same nets are selected which generally helps provide greater peer diversity, and perhaps more importantly, drastically reduces the chances an attacker is able to coerce your peer into only connecting to nodes they control.

The address manager also understands routability and Tor addresses and tries hard to only return routable addresses. In addition, it uses the information provided by the caller about connected, known good, and attempted addresses to periodically purge peers which no longer appear to be good peers as well as bias the selection toward known good peers. The general idea is to make a best effort at only providing usable addresses.

Index

Constants

View Source
const (
	// ErrAddressNotFound indicates that an operation in the address manager
	// failed due to an address lookup failure.
	ErrAddressNotFound = ErrorKind("ErrAddressNotFound")
)

These constants are used to identify a specific RuleError.

Variables

This section is empty.

Functions

func IsRoutable

func IsRoutable(netIP net.IP) bool

IsRoutable returns whether or not the passed address is routable over the public internet. This is true as long as the address is valid and is not in any reserved ranges.

func UseLogger

func UseLogger(logger slog.Logger)

UseLogger uses a specified Logger to output package logging info. This should be used in preference to SetLogWriter if the caller is also using slog.

Types

type AddrManager

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

AddrManager provides a concurrency safe address manager for caching potential peers on the Decred network.

func New

func New(dataDir string, lookupFunc func(string) ([]net.IP, error)) *AddrManager

New constructs a new address manager instance. Use Start to begin processing asynchronous address updates. The address manager uses lookupFunc for necessary DNS lookups.

func (*AddrManager) AddAddresses

func (a *AddrManager) AddAddresses(addrs []*NetAddress, srcAddr *NetAddress)

AddAddresses adds new addresses to the address manager. It enforces a max number of addresses and silently ignores duplicate addresses.

This function is safe for concurrent access.

func (*AddrManager) AddLocalAddress

func (a *AddrManager) AddLocalAddress(na *NetAddress, priority AddressPriority) error

AddLocalAddress adds na to the list of known local addresses to advertise with the given priority.

This function is safe for concurrent access.

func (*AddrManager) AddressCache

func (a *AddrManager) AddressCache() []*NetAddress

AddressCache returns a randomized subset of all known addresses.

This function is safe for concurrent access.

func (*AddrManager) Attempt

func (a *AddrManager) Attempt(addr *NetAddress) error

Attempt increases the provided known address' attempt counter and updates the last attempt time. If the address is unknown then an error is returned.

This function is safe for concurrent access.

func (*AddrManager) Connected

func (a *AddrManager) Connected(addr *NetAddress) error

Connected marks the provided known address as connected and working at the current time. If the address is unknown then an error is returned.

This function is safe for concurrent access.

func (*AddrManager) GetAddress

func (a *AddrManager) GetAddress() *KnownAddress

GetAddress returns a single address that should be routable. It picks a random one from the possible addresses with preference given to ones that have not been used recently and should not pick 'close' addresses consecutively.

This function is safe for concurrent access.

func (*AddrManager) GetBestLocalAddress

func (a *AddrManager) GetBestLocalAddress(remoteAddr *NetAddress) *NetAddress

GetBestLocalAddress returns the most appropriate local address to use for the given remote address.

This function is safe for concurrent access.

func (*AddrManager) Good

func (a *AddrManager) Good(addr *NetAddress) error

Good marks the provided known address as good. This should be called after a successful outbound connection and version exchange with a peer. If the address is unknown then an error is returned.

This function is safe for concurrent access.

func (*AddrManager) HasLocalAddress

func (a *AddrManager) HasLocalAddress(na *NetAddress) bool

HasLocalAddress asserts if the manager has the provided local address.

This function is safe for concurrent access.

func (*AddrManager) HostToNetAddress

func (a *AddrManager) HostToNetAddress(host string, port uint16, services wire.ServiceFlag) (*NetAddress, error)

HostToNetAddress parses and returns a network address given a hostname in a supported format (IPv4, IPv6, TORv2). If the hostname cannot be immediately converted from a known address format, it will be resolved using the lookup function provided to the address manager. If it cannot be resolved, an error is returned.

This function is safe for concurrent access.

func (*AddrManager) LocalAddresses

func (a *AddrManager) LocalAddresses() []LocalAddr

LocalAddresses returns a summary of local addresses information for the getnetworkinfo rpc.

This function is safe for concurrent access.

func (*AddrManager) NeedMoreAddresses

func (a *AddrManager) NeedMoreAddresses() bool

NeedMoreAddresses returns whether or not the address manager needs more addresses.

This function is safe for concurrent access.

func (*AddrManager) SetServices

func (a *AddrManager) SetServices(addr *NetAddress, services wire.ServiceFlag) error

SetServices sets the services for the provided known address to the provided value. If the address is unknown then an error is returned.

func (*AddrManager) Start

func (a *AddrManager) Start()

Start begins the core address handler which manages a pool of known addresses, timeouts, and interval based writes. If the address manager is starting or has already been started, invoking this method has no effect.

This function is safe for concurrent access.

func (*AddrManager) Stop

func (a *AddrManager) Stop() error

Stop gracefully shuts down the address manager by stopping the main handler.

This function is safe for concurrent access.

func (*AddrManager) ValidatePeerNa

func (a *AddrManager) ValidatePeerNa(localAddr, remoteAddr *NetAddress) (bool, NetAddressReach)

ValidatePeerNa returns the validity and reachability of the provided local address based on its routablility and reachability from the peer that suggested it.

This function is safe for concurrent access.

type AddressPriority

type AddressPriority int

AddressPriority type is used to describe the hierarchy of local address discovery methods.

const (
	// InterfacePrio signifies the address is on a local interface
	InterfacePrio AddressPriority = iota

	// BoundPrio signifies the address has been explicitly bounded to.
	BoundPrio

	// UpnpPrio signifies the address was obtained from UPnP.
	UpnpPrio

	// HTTPPrio signifies the address was obtained from an external HTTP service.
	HTTPPrio

	// ManualPrio signifies the address was provided by --externalip.
	ManualPrio
)

type Error

type Error struct {
	Err         error
	Description string
}

Error identifies an address manager error. It has full support for errors.Is and errors.As, so the caller can ascertain the specific reason for the error by checking the underlying error.

func (Error) Error

func (e Error) Error() string

Error satisfies the error interface and prints human-readable errors.

func (Error) Unwrap

func (e Error) Unwrap() error

Unwrap returns the underlying wrapped error.

type ErrorKind

type ErrorKind string

ErrorKind identifies a kind of error. It has full support for errors.Is and errors.As, so the caller can directly check against an error kind when determining the reason for an error.

func (ErrorKind) Error

func (e ErrorKind) Error() string

Error satisfies the error interface and prints human-readable errors.

type KnownAddress

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

KnownAddress tracks information about a known network address that is used to determine how viable an address is.

func (*KnownAddress) LastAttempt

func (ka *KnownAddress) LastAttempt() time.Time

LastAttempt returns the last time the known address was attempted.

func (*KnownAddress) NetAddress

func (ka *KnownAddress) NetAddress() *NetAddress

NetAddress returns the underlying wire.NetAddress associated with the known address.

type LocalAddr

type LocalAddr struct {
	Address string
	Port    uint16
	Score   int32
}

LocalAddr represents network address information for a local address.

type NetAddress

type NetAddress struct {
	// IP address of the peer. It is defined as a byte array to support various
	// address types that are not standard to the net module and therefore not
	// entirely appropriate to store as a net.IP.
	IP []byte

	// Port is the port of the remote peer.
	Port uint16

	// Timestamp is the last time the address was seen.
	Timestamp time.Time

	// Services represents the service flags supported by this network address.
	Services wire.ServiceFlag
}

NetAddress defines information about a peer on the network.

func NewNetAddressIPPort

func NewNetAddressIPPort(ip net.IP, port uint16, services wire.ServiceFlag) *NetAddress

NewNetAddressIPPort creates a new address manager network address given an ip, port, and the supported service flags for the address.

func (*NetAddress) AddService

func (netAddr *NetAddress) AddService(service wire.ServiceFlag)

AddService adds the provided service to the set of services that the network address supports.

func (*NetAddress) Clone

func (netAddr *NetAddress) Clone() *NetAddress

Clone creates a shallow copy of the NetAddress instance. The IP reference is shared since it is not mutated.

func (*NetAddress) GroupKey

func (na *NetAddress) GroupKey() string

GroupKey returns a string representing the network group an address is part of. This is the /16 for IPv4, the /32 (/36 for he.net) for IPv6, the string "local" for a local address, the string "tor:key" where key is the /4 of the onion address for Tor address, and the string "unroutable" for an unroutable address.

func (*NetAddress) IsRoutable

func (netAddr *NetAddress) IsRoutable() bool

IsRoutable returns a boolean indicating whether the network address is routable.

func (*NetAddress) Key

func (netAddr *NetAddress) Key() string

Key returns a string that can be used to uniquely represent the network address and includes the port.

func (*NetAddress) String

func (netAddr *NetAddress) String() string

String returns a human-readable string for the network address. This is equivalent to calling Key, but is provided so the type can be used as a fmt.Stringer.

type NetAddressReach

type NetAddressReach int

NetAddressReach represents the connection state between two addresses.

const (
	// Unreachable represents a publicly unreachable connection state
	// between two addresses.
	Unreachable NetAddressReach = 0

	// Default represents the default connection state between
	// two addresses.
	Default NetAddressReach = iota

	// Teredo represents a connection state between two RFC4380 addresses.
	Teredo

	// Ipv6Weak represents a weak IPV6 connection state between two
	// addresses.
	Ipv6Weak

	// Ipv4 represents an IPV4 connection state between two addresses.
	Ipv4

	// Ipv6Strong represents a connection state between two IPV6 addresses.
	Ipv6Strong

	// Private represents a connection state connect between two Tor addresses.
	Private
)

type NetAddressType

type NetAddressType uint8

NetAddressType is used to indicate which network a network address belongs to.

const (
	LocalAddress NetAddressType = iota
	IPv4Address
	IPv6Address
	TORv2Address
)

Jump to

Keyboard shortcuts

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