Documentation
¶
Overview ¶
Package addrmgr implements a concurrency-safe Decred address manager.
Address Manager Overview ¶
The Decred network relies on fully-validating nodes that relay transactions and blocks to other nodes around the world. The network must be dynamic because nodes will connect and disconnect as they please. Each node must manage a source of IP addresses to connect to and share with other nodes. The Decred wire protocol provides the `getaddr` and `addr` messages, allowing peers to request and share known addresses with each other. Each node needs a way to store those addresses and select peers from them. However, it is important to remember that remote peers cannot be trusted. A remote peer might send invalid addresses, or worse, only send addresses 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 that 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 reduces the chances of selecting multiple addresses from the same network, which generally helps provide greater peer diversity. More importantly, it drastically reduces the chances of an attacker coercing your peer into connecting only to nodes they control.
The address manager also understands routability, 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, as well as to bias the selection toward known good peers. The general idea is to make a best effort to only provide usable addresses.
Index ¶
- Constants
- func IsRoutable(netIP net.IP) bool
- func UseLogger(logger slog.Logger)
- type AddrManager
- func (a *AddrManager) AddAddresses(addrs []*NetAddress, srcAddr *NetAddress)
- func (a *AddrManager) AddLocalAddress(na *NetAddress, priority AddressPriority) error
- func (a *AddrManager) AddressCache(filter NetAddressTypeFilter) []*NetAddress
- func (a *AddrManager) Attempt(addr *NetAddress) error
- func (a *AddrManager) Connected(addr *NetAddress) error
- func (a *AddrManager) GetAddress() *KnownAddress
- func (a *AddrManager) GetBestLocalAddress(remoteAddr *NetAddress, filter NetAddressTypeFilter) *NetAddress
- func (a *AddrManager) Good(addr *NetAddress) error
- func (a *AddrManager) HasLocalAddress(na *NetAddress) bool
- func (a *AddrManager) IsExternalAddrCandidate(localAddr, remoteAddr *NetAddress) (bool, NetAddressReach)
- func (a *AddrManager) LocalAddresses() []LocalAddr
- func (a *AddrManager) NeedMoreAddresses() bool
- func (a *AddrManager) SetServices(addr *NetAddress, services wire.ServiceFlag) error
- func (a *AddrManager) Start()
- func (a *AddrManager) Stop() error
- type AddressPriority
- type Error
- type ErrorKind
- type KnownAddress
- type LocalAddr
- type NetAddress
- type NetAddressReach
- type NetAddressType
- type NetAddressTypeFilter
Constants ¶
const ( // ErrAddressNotFound indicates that an operation in the address manager // failed due to an address lookup failure. ErrAddressNotFound = ErrorKind("ErrAddressNotFound") // ErrUnknownAddressType indicates that the network address type could not // be determined from a network address' bytes. ErrUnknownAddressType = ErrorKind("ErrUnknownAddressType") // ErrMismatchedAddressType indicates that a network address was expected to // be a certain type, but the derived type does not match. ErrMismatchedAddressType = ErrorKind("ErrMismatchedAddressType") )
These constants are used to identify a specific RuleError.
Variables ¶
This section is empty.
Functions ¶
func IsRoutable ¶
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.
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) *AddrManager
New constructs a new address manager instance. Use Start to begin processing asynchronous address updates.
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(filter NetAddressTypeFilter) []*NetAddress
AddressCache returns a randomized subset of all addresses known to the address manager, filtered to match specified network address type(s).
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, filter NetAddressTypeFilter) *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) IsExternalAddrCandidate ¶
func (a *AddrManager) IsExternalAddrCandidate(localAddr, remoteAddr *NetAddress) (bool, NetAddressReach)
IsExternalAddrCandidate returns a boolean indicating whether a suggested Net address from a remote peer is a good candidate for this local node's public external Net address. Additionally, IsExternalAddrCandidate provides the type of reachability that the suggested localAddr has to the remoteAddr. This function is crucial because nodes need to know their own public Net addresses, but cannot determine this on their own. To avoid having to ask a centralized server, nodes listen to what remote peers say they see them as.
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.
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 ¶
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.
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.
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 addrmgr.NetAddress associated with the known address.
type NetAddress ¶
type NetAddress struct {
// Type represents the type of an address (IPv4, IPv6, Tor, etc.).
Type NetAddressType
// 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 NewNetAddressFromIPPort ¶
func NewNetAddressFromIPPort(ip net.IP, port uint16, services wire.ServiceFlag) *NetAddress
NewNetAddressFromIPPort creates a new network address given an ip, port, and the supported service flags for the address. The provided ip MUST be a valid IPv4 or IPv6 address, since this method does not perform error checking on the derived network address type. Furthermore, other types of network addresses (like Tor) will not be recognized.
func NewNetAddressFromParams ¶
func NewNetAddressFromParams(netAddressType NetAddressType, addrBytes []byte, port uint16, timestamp time.Time, services wire.ServiceFlag) (*NetAddress, error)
NewNetAddressFromParams creates a new network address from the given parameters. If the provided address type does not appear to match the address, an error is returned.
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, 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 a connection state between two IPv4 addresses. Ipv4 // Ipv6Strong represents a connection state between two IPv6 addresses. Ipv6Strong )
type NetAddressType ¶
type NetAddressType uint8
NetAddressType represents the type of an address (IPv4, IPv6, Tor, etc.).
const ( UnknownAddressType NetAddressType = 0 IPv4Address NetAddressType = 1 IPv6Address NetAddressType = 2 )
NOTE: This specifically does not use iota since the NetAddressType is used in serialization. These constants cannot be changed or re-used if new items are added.
func EncodeHost ¶
func EncodeHost(host string) (NetAddressType, []byte)
EncodeHost attempts to identify the given host address as a supported network address type, converts it to a unique encoding based on that type, and returns the result. If the host string is not recognized as any known type, then an unknown address type is returned without error.
type NetAddressTypeFilter ¶
type NetAddressTypeFilter func(NetAddressType) bool
NetAddressTypeFilter represents a function that returns whether a particular network address type matches a filter. Internally, it is used to ensure that only addresses that pass the filter's constraints are returned by the address manager.