wireguard

package
v0.0.0-...-54ed9d2 Latest Latest
Warning

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

Go to latest
Published: Jun 17, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrUnsupported = errors.New("operation not supported on this platform")

ErrUnsupported is returned by NAT-traversal operations that are not yet implemented on this platform. Callers may branch on it with errors.Is.

Functions

func DiscoverExternalAddress

func DiscoverExternalAddress(localPort int) (string, error)

DiscoverExternalAddress attempts to discover the external IP:port for the given local port WITHOUT a configured STUN server.

Endpoint discovery requires reaching out to a reflexive server (STUN). With no server supplied there is nothing to query, so this returns an honest error. Callers that have a STUN server should use DiscoverExternalAddressVia, which performs a real RFC 5389 Binding exchange.

func DiscoverExternalAddressVia

func DiscoverExternalAddressVia(stunServer string, localPort int, timeout time.Duration) (string, error)

DiscoverExternalAddressVia discovers the public (server-reflexive) endpoint by performing a real RFC 5389 STUN Binding exchange against stunServer (host:port) over UDP. The returned string is the public "ip:port" reported by the server's XOR-MAPPED-ADDRESS attribute.

localPort, when > 0, is the UDP port the discovery socket binds to so that the reflexive mapping corresponds to the WireGuard listen port.

func GenerateKeyPair

func GenerateKeyPair() (privateKey, publicKey string, err error)

GenerateKeyPair generates a new WireGuard key pair.

func KeyFingerprint

func KeyFingerprint(key string) (string, error)

KeyFingerprint returns a short, stable fingerprint for a base64-encoded WireGuard key. It is a deterministic function of the key bytes: identical keys always yield identical fingerprints and distinct keys yield distinct fingerprints (modulo SHA-256 collision resistance). The fingerprint is the first 8 bytes of SHA-256(key bytes), hex-encoded (16 hex characters).

Pure-Go: no kernel or network access.

func ParseKey

func ParseKey(key string) (wgtypes.Key, error)

ParseKey parses a base64-encoded WireGuard key.

func RemovePortMapping

func RemovePortMapping(ctx context.Context, externalPort int) error

RemovePortMapping removes a port mapping.

UPnP/NAT-PMP is not yet implemented; the function always returns an error wrapping ErrUnsupported so callers can branch with errors.Is.

func SetupPortMapping

func SetupPortMapping(ctx context.Context, internalPort, externalPort int, duration time.Duration) error

SetupPortMapping creates a UPnP/NAT-PMP port mapping.

UPnP/NAT-PMP is not yet implemented; the function always returns an error wrapping ErrUnsupported so callers can branch with errors.Is.

func SpotDrainHook

func SpotDrainHook(mc *MeshCoordinator) cloudspot.Hooks

SpotDrainHook builds a cloudspot.Hooks value whose StopAdmission step calls TeardownPeers on the given MeshCoordinator. Wire the returned Hooks into a cloudspot.Handler to get automatic peer teardown on a cloud-spot preemption notice.

The returned Hooks.StopAdmission respects ctx cancellation / deadline so the drain lifecycle's timeout propagates correctly into the teardown.

Types

type Action

type Action int

Action is the policy verdict: ALLOW or DENY.

const (
	// ActionAllow permits traffic matching the policy.
	ActionAllow Action = iota
	// ActionDeny blocks traffic matching the policy.
	ActionDeny
)

func (Action) String

func (a Action) String() string

String returns the human-readable action name.

type Config

type Config struct {
	InterfaceName string
	ListenPort    int
	PrivateKey    string
	Address       string // CIDR
	MTU           int

	// NAT traversal
	EnableUPnP        bool
	EnableNATPMapping bool

	// NoOp disables real WireGuard interface operations.
	// Useful for testing on platforms without WireGuard kernel support.
	NoOp bool

	// KeyOverlap is the duration the superseded device key remains valid after
	// RotateKeysTracked is called, so in-flight traffic encrypted under it is
	// not dropped during rotation. Zero disables the grace window (the old key
	// is invalidated immediately).
	KeyOverlap time.Duration
}

Config holds WireGuard interface configuration.

func DefaultConfig

func DefaultConfig() *Config

DefaultConfig returns sensible defaults.

type EnforcementRuleset

type EnforcementRuleset struct {
	// NodeID is the node this ruleset targets.
	NodeID string

	// Ruleset is the pf(4)-style ruleset text (portable ASCII, applicable on
	// macOS via /etc/pf.conf and on Linux via a compatible nft/iptables wrapper).
	// Each DENY policy produces one "block" line; each ALLOW policy produces one
	// "pass" line.
	Ruleset string
}

EnforcementRuleset is the concrete result of translating the PolicyEngine's decision table into firewall rules for a specific node.

type HolePunchState

type HolePunchState int

HolePunchState represents the outcome state of a UDP hole-punch attempt.

const (
	// HolePunchPending means the punch has not completed or timed out yet.
	HolePunchPending HolePunchState = iota
	// HolePunchConnected means both peers successfully exchanged a datagram.
	HolePunchConnected
	// HolePunchTimedOut means the punch window expired before both sides confirmed.
	HolePunchTimedOut
	// HolePunchRelaying means hole-punch failed and traffic is going via relay.
	HolePunchRelaying
)

func (HolePunchState) String

func (s HolePunchState) String() string

String implements fmt.Stringer for HolePunchState.

type HolePuncher

type HolePuncher struct {
	// LocalConn is the UDP connection to punch from. The caller owns it and is
	// responsible for closing it after the HolePuncher returns.
	LocalConn *net.UDPConn

	// RemoteAddr is the peer's public UDP address (discovered via STUN) that we
	// are attempting to punch through to.
	RemoteAddr *net.UDPAddr

	// Timeout is the maximum time to wait for the hole-punch to complete before
	// declaring failure. Zero defaults to 5 seconds.
	Timeout time.Duration

	// ProbeInterval is how often probe datagrams are retransmitted while waiting
	// for the peer's probe to arrive. Zero defaults to 200 ms.
	ProbeInterval time.Duration

	// ProbePayload is the datagram content used as the punch probe. If nil a
	// one-byte probe "\x00" is used.
	ProbePayload []byte

	// RelayAddr, when non-nil, is attempted as a fallback address if the direct
	// hole-punch times out. It should be a TURN/STUN relay socket address.
	RelayAddr *net.UDPAddr
}

HolePuncher orchestrates RFC-style UDP hole-punching between two NAT-ed peers. It uses a simultaneous open strategy: both sides send a probe datagram to each other at the same time, which opens NAT bindings in both directions.

If the direct punch does not complete within Timeout, the puncher falls back to the optional RelayAddr (STUN/TURN style relay). If no RelayAddr is configured the result state is HolePunchTimedOut.

func (*HolePuncher) Punch

func (hp *HolePuncher) Punch(ctx context.Context) (*holePunchResult, error)

Punch performs the hole-punch attempt and returns the result. It is safe to call from multiple goroutines (each call is fully independent — no shared mutable state beyond the LocalConn).

type InterfaceSection

type InterfaceSection struct {
	PrivateKey string
	Address    string
	ListenPort int
	MTU        int
}

InterfaceSection holds the parsed `[Interface]` fields.

type InterfaceStats

type InterfaceStats struct {
	Name      string
	Address   string
	Port      int
	PublicKey string
	Peers     int
	RxBytes   int64
	TxBytes   int64
}

InterfaceStats holds interface-level statistics.

type KeyState

type KeyState struct {
	// Generation is a monotonically increasing counter. Generation 0 is the
	// key the manager started with; each rotation increments it by one.
	Generation uint64
	// PublicKey is the base64-encoded Curve25519 public key for this state.
	PublicKey string
	// Fingerprint is KeyFingerprint(PublicKey).
	Fingerprint string
	// RotatedAt is the wall-clock time this state became active.
	RotatedAt time.Time
}

KeyState is an immutable snapshot of the manager's active key material at a given rotation generation. It is safe to retain a KeyState across subsequent rotations — it is a value copy and never mutated in place.

func (KeyState) Supersedes

func (s KeyState) Supersedes(other KeyState) bool

Supersedes reports whether s is a strictly later key state than other — i.e. s was produced by a rotation that came after other. A state never supersedes itself or any state at an equal/greater generation.

type LabelSelector

type LabelSelector struct {
	// MatchLabels is a set of required key=value label pairs. All must match.
	MatchLabels map[string]string
}

LabelSelector selects nodes whose Labels map contains all key=value pairs in MatchLabels. An empty MatchLabels selector matches ALL nodes.

func (LabelSelector) Matches

func (s LabelSelector) Matches(labels map[string]string) bool

Matches reports whether the node's label set satisfies this selector. An empty MatchLabels matches everything.

type Manager

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

Manager manages a WireGuard interface and its peers.

func NewManager

func NewManager(cfg *Config) (*Manager, error)

NewManager creates a WireGuard manager.

func (*Manager) ActiveKeys

func (m *Manager) ActiveKeys() []string

ActiveKeys returns the set of public keys currently accepted for THIS manager's device identity — the live key plus any superseded keys whose grace/overlap window has not yet elapsed. The live key is always first.

This builds on the same per-peer key-overlap machinery used by RotatePeerKeyWithOverlap; callers use it so that mesh peers that have not yet received a rotation notice can still establish sessions with the old key during the configured overlap window.

Pure-Go: reads only in-memory state.

func (*Manager) AddPeer

func (m *Manager) AddPeer(peer *PeerConfig) error

AddPeer adds or updates a peer.

func (*Manager) CurrentKeyState

func (m *Manager) CurrentKeyState() KeyState

CurrentKeyState returns an immutable snapshot of the manager's active key state. The returned value is a copy and is unaffected by later rotations.

If no public key has been derived yet (e.g. the configured private key is empty/invalid), PublicKey and Fingerprint may be empty but Generation is still meaningful.

func (*Manager) DisableKeyRotation

func (m *Manager) DisableKeyRotation()

DisableKeyRotation stops key rotation.

func (*Manager) EnableKeyRotation

func (m *Manager) EnableKeyRotation(interval time.Duration)

EnableKeyRotation starts periodic key rotation.

func (*Manager) GenerateConfigString

func (m *Manager) GenerateConfigString() (string, error)

GenerateConfigString renders the full WireGuard configuration for this manager: an `[Interface]` block followed by one `[Peer]` block per configured peer. A `# KeyGeneration: N` comment records the current key rotation generation so that a regenerated config can be detected as superseding an earlier one.

Pure-Go: reads only in-memory state, no kernel or network access.

func (*Manager) GetPeer

func (m *Manager) GetPeer(publicKey string) (*PeerConfig, error)

GetPeer returns a specific peer.

func (*Manager) InterfaceStats

func (m *Manager) InterfaceStats() (*InterfaceStats, error)

InterfaceStats returns interface-level statistics.

func (*Manager) IsPeerKeyValid

func (m *Manager) IsPeerKeyValid(identity, publicKey string) bool

IsPeerKeyValid reports whether publicKey is currently accepted for the peer identity (live key or within an unexpired overlap window).

func (*Manager) KeyGeneration

func (m *Manager) KeyGeneration() uint64

KeyGeneration returns the current key generation counter.

func (*Manager) ListPeers

func (m *Manager) ListPeers() ([]*PeerConfig, error)

ListPeers returns all configured peers.

func (*Manager) PeerHandshakeTime

func (m *Manager) PeerHandshakeTime(publicKey string) (time.Duration, error)

PeerHandshakeTime returns time since last handshake.

func (*Manager) PeerKeyState

func (m *Manager) PeerKeyState(identity string) PeerKeyState

PeerKeyStateAt returns the full PeerKeyState for the identity as of the manager's clock.

func (*Manager) PeerRxTx

func (m *Manager) PeerRxTx(publicKey string) (rx, tx int64, err error)

PeerRxTx returns bytes received/transmitted for a peer.

func (*Manager) RemovePeer

func (m *Manager) RemovePeer(publicKey string) error

RemovePeer removes a peer by public key.

func (*Manager) RotateKeys

func (m *Manager) RotateKeys() (newPublicKey string, err error)

RotateKeys generates new key pair and updates interface.

func (*Manager) RotateKeysTracked

func (m *Manager) RotateKeysTracked() (*RotationResult, error)

RotateKeysTracked generates a fresh Curve25519 keypair, installs it as the manager's active key (superseding the previous one), advances the generation counter, and returns a RotationResult describing the change.

If m.config.KeyOverlap > 0 the superseded public key is retained in the active-keys grace window for that duration, so remote peers that have not yet received the rotation notice can still establish sessions. The window is tracked internally via the same per-peer machinery used by RotatePeerKeyWithOverlap; callers retrieve the live + grace keys via ActiveKeys().

On non-NoOp managers the new private key is pushed to the device via wgctrl; in NoOp mode only the in-memory config is updated. This method is purely computational with respect to key generation — it performs no network calls.

func (*Manager) RotatePeerKeyWithOverlap

func (m *Manager) RotatePeerKeyWithOverlap(identity, newPublicKey string, overlap time.Duration) (PeerKeyState, error)

RotatePeerKeyWithOverlap rotates the public key for the logical peer identified by identity. The newPublicKey becomes the live key immediately, while the previous live key (if any) is kept valid for the overlap duration so traffic already encrypted under it is accepted until the grace window closes. An overlap <= 0 expires the old key immediately.

It returns the resulting PeerKeyState. The returned ValidKeys reflects expiry as of the manager's clock at call time (already-expired old keys are pruned).

Pure-Go: updates only in-memory state, no kernel or network access.

func (*Manager) Start

func (m *Manager) Start() error

Start initializes the WireGuard interface.

func (*Manager) Stop

func (m *Manager) Stop() error

Stop tears down the interface.

func (*Manager) ValidPeerKeys

func (m *Manager) ValidPeerKeys(identity string) []string

ValidPeerKeys returns the set of public keys currently accepted for the peer identity, pruning any keys whose overlap window has elapsed. The newest live key is first.

Pure-Go: reads only in-memory state.

type MeshConfig

type MeshConfig struct {
	// NodeID is the ID of the node this config belongs to.
	NodeID string

	// ConfigString is the rendered wg-quick-compatible configuration text,
	// including an [Interface] block and one [Peer] block per remote node.
	ConfigString string

	// Peers is the ordered list of peer public keys included in this config.
	// len(Peers) == N-1 for an N-node mesh.
	Peers []string
}

MeshConfig is the generated WireGuard configuration for a single node in an N-node full mesh. For node i it contains one [Peer] block for every other node j (i ≠ j).

func GenerateMeshConfigs

func GenerateMeshConfigs(nodes []MeshNode, tag string) ([]*MeshConfig, error)

GenerateMeshConfigs generates a full-mesh WireGuard configuration for every node in nodes. Each node receives a MeshConfig containing an [Interface] block and one [Peer] block per other node.

The listen port is fixed at 51820 (the canonical WireGuard port). AllowedIPs for each peer is the /32 (IPv4) or /128 (IPv6) host address derived from that peer's Address field.

The optional tag parameter is appended as a comment on the first line of every generated config, enabling callers to embed a per-run UUID or other tracing label. Pass "" to omit the tag comment.

Pure-Go: no kernel or network access. Works identically on every OS.

func RotateMeshNodeKey

func RotateMeshNodeKey(nodes []MeshNode, nodeID string, tag string) (newPubKey string, configs []*MeshConfig, err error)

RotateMeshNodeKey rotates the key for the node identified by nodeID within the nodes slice: it generates a fresh keypair, replaces that node's PrivateKey in-place, and regenerates all mesh configs using the same tag.

The returned slice is a fresh generation of []*MeshConfig. Only the configs that reference nodeID (either as the interface owner or as a peer) change; all other pairwise relationships are structurally identical.

Returns the new public key for the rotated node alongside the configs.

Pure-Go: no kernel or network access.

type MeshCoordinator

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

MeshCoordinator coordinates WireGuard peers with SWIM membership.

func NewMeshCoordinator

func NewMeshCoordinator(wg *Manager, swim *swim.Protocol) *MeshCoordinator

NewMeshCoordinator creates a coordinator.

func (*MeshCoordinator) OnMemberJoined

func (mc *MeshCoordinator) OnMemberJoined(member *swim.Member)

OnMemberJoined is called when SWIM detects a new member.

func (*MeshCoordinator) OnMemberLeft

func (mc *MeshCoordinator) OnMemberLeft(memberID string)

OnMemberLeft is called when SWIM detects a member departure.

func (*MeshCoordinator) OnMemberSuspect

func (mc *MeshCoordinator) OnMemberSuspect(memberID string)

OnMemberSuspect is called when SWIM suspects a member.

func (*MeshCoordinator) Start

func (mc *MeshCoordinator) Start() error

Start begins automatic peer sync with SWIM membership.

func (*MeshCoordinator) Stop

func (mc *MeshCoordinator) Stop() error

Stop stops automatic sync.

func (*MeshCoordinator) SyncNow

func (mc *MeshCoordinator) SyncNow() error

SyncNow performs a one-time sync of SWIM members to WireGuard peers.

func (*MeshCoordinator) TeardownPeers

func (mc *MeshCoordinator) TeardownPeers(ctx context.Context) (removed int, err error)

TeardownPeers stops the MeshCoordinator (idempotent) and removes every peer that is currently tracked by the underlying Manager. It returns the number of peers that were removed on this call.

Idempotency contract: a second (and any subsequent) call after all peers have already been removed returns (0, nil) — not an error.

Thread safety: it is safe to call TeardownPeers concurrently; only the first caller will observe a non-zero removed count.

type MeshNode

type MeshNode struct {
	// ID is a caller-chosen stable identifier for this node (e.g. "node-0").
	ID string

	// PrivateKey is the base64-encoded Curve25519 private key for this node.
	// GenerateKeyPair() produces a suitable value.
	PrivateKey string

	// Address is the CIDR address assigned to this node's WireGuard interface
	// (e.g. "10.200.0.1/24").  Every peer in the mesh is given AllowedIPs equal
	// to the host /32 (or /128) derived from this address.
	Address string

	// Endpoint is the publicly-reachable "host:port" for this node
	// (e.g. "203.0.113.1:51820").  It is written into every peer config that
	// references this node.
	Endpoint string
}

MeshNode describes a single node participating in the WireGuard mesh. All fields are mandatory for config generation.

type NATTraversal

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

NATTraversal handles NAT endpoint discovery for WireGuard.

type NetworkPolicy

type NetworkPolicy struct {
	// Name is a stable, human-readable identifier. Embedded in generated rulesets.
	Name string

	// Action is ALLOW or DENY.
	Action Action

	// FromSelector selects source nodes by labels.
	FromSelector LabelSelector

	// ToSelector selects destination nodes by labels.
	ToSelector LabelSelector

	// Ports is the set of TCP/UDP destination ports this policy applies to.
	// An empty slice means "match all ports".
	Ports []uint16
}

NetworkPolicy describes one segmentation rule.

type Node

type Node struct {
	// ID is the stable node identifier (e.g. "node-a", the SWIM member ID).
	ID string

	// Labels is the key=value label set used by LabelSelector.Matches.
	Labels map[string]string

	// WireGuardIP is the WireGuard interface IP address (without prefix length).
	// Used when generating firewall rules. May be empty if not needed.
	WireGuardIP string
}

Node is a WireGuard mesh participant with a set of labels used for selector matching. WireGuardIP is the IP address assigned to this node's WG interface (e.g. "10.200.0.1"); it is used in the generated enforcement ruleset.

type ParsedConfig

type ParsedConfig struct {
	Interface InterfaceSection
	Peers     []PeerConfig
}

ParsedConfig is the structured result of parsing a WireGuard config string.

func ParseConfigString

func ParseConfigString(s string) (*ParsedConfig, error)

ParseConfigString parses a WireGuard configuration string (as produced by GenerateConfigString or wg-quick) back into structured form. It is the inverse of GenerateConfigString for the fields both support, enabling round-trip testing.

Pure-Go: no kernel or network access.

type PeerConfig

type PeerConfig struct {
	PublicKey           string
	PresharedKey        string // optional
	AllowedIPs          []string
	Endpoint            string // host:port
	PersistentKeepalive int    // seconds
}

PeerConfig holds configuration for a single peer.

func (*PeerConfig) ConfigString

func (p *PeerConfig) ConfigString() (string, error)

ConfigString renders this peer as a WireGuard `[Peer]` configuration block.

AllowedIPs are validated as CIDRs and joined comma-separated on a single line. Endpoint and PresharedKey are emitted only when set, and validated when present. PersistentKeepalive is emitted only when > 0 (0 means disabled and is omitted, matching wg-quick semantics).

Pure-Go: no kernel or network access.

type PeerKeyState

type PeerKeyState struct {
	// Identity is the caller-chosen logical peer identity.
	Identity string
	// Current is the newest (live) public key for the peer.
	Current string
	// ValidKeys is every public key that is currently accepted for the peer,
	// including Current and any not-yet-expired superseded keys. Order is
	// stable: Current first, then superseded keys by descending expiry.
	ValidKeys []string
}

PeerKeyState reports the currently-valid public keys for a peer identity.

type PeerPuncher

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

PeerPuncher coordinates a symmetric hole-punch where BOTH endpoints are represented by local UDP sockets (used in tests and single-host deployments). In production each peer runs a HolePuncher independently.

func NewPeerPuncher

func NewPeerPuncher() (*PeerPuncher, error)

NewPeerPuncher creates two loopback UDP sockets and returns a PeerPuncher that can perform a symmetric hole-punch between them. Close must be called when done.

func (*PeerPuncher) AddrA

func (pp *PeerPuncher) AddrA() *net.UDPAddr

AddrA returns the local address of socket A.

func (*PeerPuncher) AddrB

func (pp *PeerPuncher) AddrB() *net.UDPAddr

AddrB returns the local address of socket B.

func (*PeerPuncher) Close

func (pp *PeerPuncher) Close()

Close releases both UDP sockets.

func (*PeerPuncher) PunchBoth

func (pp *PeerPuncher) PunchBoth(ctx context.Context, timeout time.Duration) (resA, resB *holePunchResult, err error)

PunchBoth launches simultaneous hole-punch from A→B and B→A and waits for both to reach HolePunchConnected within timeout. Returns both results. Hard-fails if either side does not reach CONNECTED (both are loopback sockets, so success is guaranteed unless timeout is absurdly short or the OS rejects the packets, which cannot happen on loopback).

type PolicyEngine

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

PolicyEngine evaluates a set of NetworkPolicies against a node inventory.

func NewPolicyEngine

func NewPolicyEngine(policies []*NetworkPolicy, nodes []*Node) (*PolicyEngine, error)

NewPolicyEngine builds a PolicyEngine from the supplied policies and nodes. Policies are evaluated in DENY-wins order (see package doc). Node IDs must be unique; duplicate IDs cause an error.

func (*PolicyEngine) Decide

func (e *PolicyEngine) Decide(srcNodeID, dstNodeID string, port uint16) (Action, error)

Decide evaluates all policies and returns the access decision for a packet from srcNodeID to dstNodeID on the given destination port.

Resolution: DENY-wins. If any matching policy is DENY, the result is DENY. If at least one matching policy is ALLOW (and none are DENY), the result is ALLOW. If no policy matches, the result is ALLOW (default-permit).

Returns an error only if src or dst node IDs are not found in the inventory.

func (*PolicyEngine) GenerateEnforcementRuleset

func (e *PolicyEngine) GenerateEnforcementRuleset(nodeID string) (*EnforcementRuleset, error)

GenerateEnforcementRuleset produces the pf(4)-compatible ruleset for nodeID. It evaluates every (src, dst, port) combination implied by the policies and emits:

  • A "block" line for each DENY policy that applies to or from this node.
  • A "pass" line for each ALLOW policy that applies to or from this node.

The output is deterministic: policies appear in the order they were registered. The per-policy Name is embedded in a comment on each rule so tracing is easy.

CLAUDE-2 BOUNDARY JUSTIFICATION: This function generates the TEXT of the ruleset that WOULD be applied. Actually loading it into pf(4) (via pfctl -f) or nftables requires root privileges and a live WireGuard interface — capabilities that are not available (and should not be exercised) in the hermetic test environment on macOS. The correctness of the DECISION LOGIC and the GENERATED TEXT are fully proven in unit tests. Applying the ruleset to live kernel packet filtering is a deployment-layer concern.

func (*PolicyEngine) GenerateFullMeshRuleset

func (e *PolicyEngine) GenerateFullMeshRuleset() (map[string]*EnforcementRuleset, error)

GenerateFullMeshRuleset generates the enforcement rulesets for ALL nodes in the engine. The returned map is keyed by node ID.

type RotationResult

type RotationResult struct {
	Generation          uint64
	NewPrivateKey       string
	NewPublicKey        string
	NewFingerprint      string
	PreviousPublicKey   string
	PreviousFingerprint string
}

RotationResult records the outcome of a tracked key rotation, including the fresh key material and the (now superseded) previous key for audit/detection.

type STUNClient

type STUNClient struct {
	// Timeout bounds the read of the single Binding Response. Zero means a
	// 5-second default is applied.
	Timeout time.Duration
}

STUNClient is a minimal RFC 5389 STUN Binding client used to discover the public (server-reflexive) UDP endpoint of a local socket. It implements just enough of the protocol to encode a Binding Request and decode the XOR-MAPPED-ADDRESS attribute of the reply.

The client performs real UDP I/O; tests exercise it against a local fake STUN server bound to 127.0.0.1, so no external STUN service is contacted.

func (*STUNClient) DiscoverPublicEndpoint

func (c *STUNClient) DiscoverPublicEndpoint(serverAddr string) (string, error)

DiscoverPublicEndpoint sends a STUN Binding Request to serverAddr (host:port) over UDP and returns the public (server-reflexive) endpoint decoded from the reply's XOR-MAPPED-ADDRESS attribute, formatted as "ip:port".

It validates the magic cookie and that the response transaction ID matches the request, rejecting spoofed or malformed replies.

func (*STUNClient) DiscoverPublicUDPAddr

func (c *STUNClient) DiscoverPublicUDPAddr(serverAddr string) (*net.UDPAddr, error)

DiscoverPublicUDPAddr is like DiscoverPublicEndpoint but returns the decoded *net.UDPAddr.

Jump to

Keyboard shortcuts

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