Documentation
¶
Overview ¶
Package mesh owns the WireGuard overlay (ADR-0003). The Manager interface is consumed by the daemon wiring and the agent; implementations:
- device manager with wireguard-go / kernel WG (tasks T-18..T-21, T-57/58)
- Disabled (single-node mode, returned by NewDisabled)
- testutil fake (simcluster)
Index ¶
- Constants
- func DiscoKey(pub wgtypes.Key, caHash []byte) []byte
- func EnsureNodeKey(path string) (string, error)
- func RunPeerSync(ctx context.Context, cfg PeerSyncConfig) error
- type DeviceManager
- func (dm *DeviceManager) ApplyPeers(_ context.Context, peers *clusterv1.PeerSet) error
- func (dm *DeviceManager) Down(_ context.Context) error
- func (dm *DeviceManager) InjectRelayed(srcNodeID string, payload []byte)
- func (dm *DeviceManager) LastHandshakes() (map[string]int64, error)
- func (dm *DeviceManager) PublicKey() (string, error)
- func (dm *DeviceManager) PunchNow(peerID string, endpoints []netip.AddrPort, at time.Time)
- func (dm *DeviceManager) Status() Status
- func (dm *DeviceManager) Up(_ context.Context, cfg NodeConfig) error
- type Disabled
- type DiscoPinger
- type DiscoResponder
- type Gossip
- type GossipConfig
- type Manager
- type MeshsockConfig
- type NodeConfig
- type PeerSyncConfig
- type Status
Constants ¶
const ( // GossipPort is the memberlist bind port. It is bound to the mesh IP only — // never a public interface. GossipPort = 7946 )
Gossip is a memberlist-based failure detector (T-56). Control nodes run it over the mesh: SWIM-style probing spots a dead node within a few seconds — far faster than the 30s heartbeat deadline — and feeds the same durable SetNodeStatus path as the heartbeat monitor (T-21). The two detectors are combined by Decide so neither can flap a node's status on its own.
Variables ¶
This section is empty.
Functions ¶
func EnsureNodeKey ¶
EnsureNodeKey loads or creates the WG private key at path and returns its public key (base64). A joining node calls this to advertise its public key in the join request before the device is brought up; Up reuses the same path so the advertised key matches the running device.
func RunPeerSync ¶
func RunPeerSync(ctx context.Context, cfg PeerSyncConfig) error
RunPeerSync keeps a WatchPeers stream open and applies every pushed PeerSet to the mesh device, reconnecting with backoff. Blocks until ctx is canceled.
Types ¶
type DeviceManager ¶
type DeviceManager struct {
// contains filtered or unexported fields
}
DeviceManager implements mesh.Manager over a real WireGuard device.
func NewDeviceManager ¶
func NewDeviceManager(log *slog.Logger) *DeviceManager
NewDeviceManager builds a mesh manager backed by a real WG device. The kernel-vs-userspace choice is made at Up time (kernel preferred on Linux).
func (*DeviceManager) ApplyPeers ¶
ApplyPeers reconciles the device's peer set to exactly `peers`.
func (*DeviceManager) Down ¶
func (dm *DeviceManager) Down(_ context.Context) error
Down tears the device down.
func (*DeviceManager) InjectRelayed ¶
func (dm *DeviceManager) InjectRelayed(srcNodeID string, payload []byte)
InjectRelayed queues a relay-received WG packet for WireGuard — called by the relay client's read loop. No-op without meshsock.
func (*DeviceManager) LastHandshakes ¶
func (dm *DeviceManager) LastHandshakes() (map[string]int64, error)
LastHandshakes returns the last-handshake time (unix seconds, 0 = never) per peer, keyed by hex public key. Useful for path diagnostics and integration tests.
func (*DeviceManager) PublicKey ¶
func (dm *DeviceManager) PublicKey() (string, error)
PublicKey returns the node's WG public key, generating the keypair on first use. Valid before Up (the key path is taken from the last Up config or, if Up has not run, this returns an error asking for a path).
func (*DeviceManager) PunchNow ¶
PunchNow schedules a probe burst toward peerID at `at` — called when control pushes a PunchCommand over the node's PunchStream. No-op without meshsock.
func (*DeviceManager) Status ¶
func (dm *DeviceManager) Status() Status
Status reports the current device state.
func (*DeviceManager) Up ¶
func (dm *DeviceManager) Up(_ context.Context, cfg NodeConfig) error
Up creates and configures the WG device (idempotent). It requires root/CAP_NET_ADMIN.
type Disabled ¶
type Disabled struct{}
Disabled is the single-node no-mesh implementation: everything is a no-op and Status reports Enabled=false. The daemon then binds all internal services to 127.0.0.1.
func NewDisabled ¶
func NewDisabled() Disabled
type DiscoPinger ¶
type DiscoPinger struct {
NodeID string
Key []byte
Controls []string // control disco endpoints "ip:port"
Interval time.Duration
Clock clock.Clock
Report func(observedEndpoint string)
Logger *slog.Logger
// contains filtered or unexported fields
}
DiscoPinger is the node-side prober. It pings each control's disco endpoint and reports the reflexive address the control observed.
func (*DiscoPinger) Run ¶
func (p *DiscoPinger) Run(ctx context.Context)
Run probes every Interval until ctx is canceled.
type DiscoResponder ¶
type DiscoResponder struct {
// contains filtered or unexported fields
}
DiscoResponder is the control-side echo server. For each valid ping it returns a pong carrying the observed UDP source address.
func NewDiscoResponder ¶
func NewDiscoResponder(addr string, keyForNode func(string) ([]byte, bool), log *slog.Logger) (*DiscoResponder, error)
NewDiscoResponder binds a UDP listener on addr ("ip:port").
func (*DiscoResponder) Addr ¶
func (r *DiscoResponder) Addr() string
Addr is the bound listen address.
func (*DiscoResponder) Serve ¶
func (r *DiscoResponder) Serve(ctx context.Context)
Serve reads and answers pings until ctx is canceled.
type Gossip ¶
type Gossip struct {
// contains filtered or unexported fields
}
Gossip owns the running memberlist and its liveness tracker.
func NewGossip ¶
func NewGossip(cfg GossipConfig) (*Gossip, error)
NewGossip starts memberlist bound to the mesh IP and joins the given peers (best-effort — a node that cannot reach any peer yet still runs and will be discovered when a peer probes it).
func (*Gossip) Snapshot ¶
func (g *Gossip) Snapshot() map[string]nodehealth.GossipLiveness
Snapshot returns the current gossip liveness view keyed by node id.
type GossipConfig ¶
type GossipConfig struct {
// NodeID is this node's zattera id — used as the memberlist node name so
// events map straight back to nodes.
NodeID string
// BindAddr is the mesh IP to bind (e.g. 10.90.0.1). Never a public IP.
BindAddr string
// Peers are other control nodes' mesh IPs to join (host or host:port).
Peers []string
// CAHash is the cluster CA hash; the gossip encryption key derives from it,
// so only cluster members can join or read the gossip.
CAHash []byte
Clock clock.Clock
Logger *slog.Logger
}
GossipConfig configures the gossip failure detector.
type Manager ¶
type Manager interface {
// Up creates/configures the WG device. Idempotent.
Up(ctx context.Context, cfg NodeConfig) error
// ApplyPeers reconciles the device's peer set to exactly `peers`
// (declarative full set — implementations diff internally).
ApplyPeers(ctx context.Context, peers *clusterv1.PeerSet) error
// Down tears the device down.
Down(ctx context.Context) error
Status() Status
// PublicKey returns the node's WG public key (generating a keypair on
// first use), valid before Up.
PublicKey() (string, error)
}
Manager is the per-node mesh controller.
type MeshsockConfig ¶
type MeshsockConfig struct {
NodeID string
CAHash []byte
// Punch coordinates hole punching via control (nil disables punching).
Punch meshsock.PunchRequester
// Relay sends WG packets via the control TCP relay (nil disables the relay).
Relay meshsock.RelaySender
}
MeshsockConfig parameterizes the meshsock datapath (T-57/T-58).
type NodeConfig ¶
type NodeConfig struct {
// PrivateKeyPath stores the WG private key (0600). Generated when absent.
PrivateKeyPath string
MeshIP netip.Addr
// ListenPort for WireGuard UDP (default 51820).
ListenPort uint16
// InterfaceName defaults to "zt0" (utunN chosen automatically on darwin).
InterfaceName string
// Meshsock, when set, brings the device up on the userspace meshsock bind
// (UDP hole punching + relay, phases C/D). Kernel WG cannot use a custom
// bind, so this forces userspace.
Meshsock *MeshsockConfig
}
NodeConfig is what a node needs to bring its mesh interface up.
type PeerSyncConfig ¶
type PeerSyncConfig struct {
NodeID string
Manager Manager
Clock clock.Clock
Logger *slog.Logger
// Dial opens a connection to a control node's MeshService. Called on every
// (re)connect; the returned closer is invoked when the stream ends.
Dial func(ctx context.Context) (grpc.ClientConnInterface, func() error, error)
// OnPeers, when set, is called with every PeerSet received (before it is
// applied). A worker uses it to keep its control-node failover set current.
OnPeers func(*clusterv1.PeerSet)
}
PeerSyncConfig configures the node-side peer synchronizer.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package meshsock is the custom wireguard-go conn.Bind (ADR-0003 Phase C/D): one UDP socket multiplexes WireGuard transport packets and disco probe frames, a per-peer path state machine upgrades hub-routed peers to direct or hole-punched UDP paths, and (Phase D) falls back to a TCP relay when no UDP path works.
|
Package meshsock is the custom wireguard-go conn.Bind (ADR-0003 Phase C/D): one UDP socket multiplexes WireGuard transport packets and disco probe frames, a per-peer path state machine upgrades hub-routed peers to direct or hole-punched UDP paths, and (Phase D) falls back to a TCP relay when no UDP path works. |
|
Package relay is the Phase D DERP-lite fallback (ADR-0003): every control node runs an mTLS TCP relay; a meshsock node with no working UDP path frames its already-encrypted WireGuard packets as (dst node, payload) and the relay forwards them to the destination's connection.
|
Package relay is the Phase D DERP-lite fallback (ADR-0003): every control node runs an mTLS TCP relay; a meshsock node with no working UDP path frames its already-encrypted WireGuard packets as (dst node, payload) and the relay forwards them to the destination's connection. |