node

package
v0.1.2 Latest Latest
Warning

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

Go to latest
Published: Apr 5, 2026 License: MIT Imports: 40 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ClientTLSConfig

func ClientTLSConfig(nodeCert tls.Certificate, caPool *x509.CertPool) *tls.Config

ClientTLSConfig returns a TLS config that presents the node cert and verifies peers against the CA.

Overlay networks don't use hostname-based certificate verification — peer addresses are determined by the gossip table, not DNS. We skip Go's built-in hostname check and instead verify the cert chain manually against the CA pool. This is the same approach used by WireGuard, Tailscale, and other mesh VPNs.

func Debugf

func Debugf(format string, args ...any)

func Errorf

func Errorf(format string, args ...any)

func FECFrameRead

func FECFrameRead(r io.Reader) (frameType byte, groupID uint16, index byte, payload []byte, err error)

fecFrameRead reads one FEC-framed packet.

func FormatPortRanges

func FormatPortRanges(ports []PortRange) string

FormatPortRanges formats port ranges as a human-readable string.

func HandleRelayStream

func HandleRelayStream(stream net.Conn, reader *bufio.Reader, req TunnelRequest, selfID string, callerNodeID string, router *Router, acls *ACLTable, metaLookup MetaLookup)

HandleRelayStream is called by the dispatcher when a tunnel stream arrives. callerNodeID is the verified identity of the peer that opened the stream (from TLS CN).

func Infof

func Infof(format string, args ...any)

func LinkScore

func LinkScore(e PeerEntry) float64

LinkScore computes a composite routing score for a peer entry. Lower score = better path. Uses latency, loss rate, and hop count.

func LoadCAPool

func LoadCAPool(caCertPEM []byte) (*x509.CertPool, error)

LoadCAPool loads only the CA cert for client nodes (no private key needed).

func LoadNodePubKey

func LoadNodePubKey(path string) (ed25519.PublicKey, error)

LoadNodePubKey loads an Ed25519 public key from a PEM file. Useful for the operator authorize flow.

func MatchesNode

func MatchesNode(pattern, nodeID string, meta NodeMeta) bool

matchesNode checks if pattern matches nodeID, considering tags and names. Pattern formats:

  • "*" or glob: matched against nodeID
  • "tag:<name>": true if the node has that tag
  • plain string that isn't a glob: matched as name first, then as nodeID glob

func MeshIPFromNodeID

func MeshIPFromNodeID(nodeID string) net.IP

MeshIPFromNodeID derives a deterministic mesh IP from a node ID string. nodeID is a 16-char hex string; we use the first 4 hex chars (2 bytes). Result is in the range 10.100.0.0–10.100.255.255.

func NewFECDecoder

func NewFECDecoder() *fecDecoder

func NewFECEncoder

func NewFECEncoder() *fecEncoder

func RegisterService

func RegisterService(table *Table, selfID, addr string, pubKey []byte, isCA bool, svc ServiceRecord)

RegisterService adds a service to the node's self-entry in the gossip table. Other nodes learn about it on the next gossip push.

func SavePeers

func SavePeers(dataDir string, entries []PeerEntry) error

SavePeers atomically writes entries to peers.json in dataDir.

func ServeTCP

func ServeTCP(listenAddr string, router *Router, aclTable *ACLTable, selfID string, isRevoked func(string) bool) error

ServeTCP listens for inbound TCP client connections and relays them. Uses SO_REUSEPORT so the kernel can load-balance across multiple goroutines.

func SetLogLevel

func SetLogLevel(l LogLevel)

SetLogLevel sets the global log level.

func StoreJoinResult

func StoreJoinResult(dir string, resp JoinResponse) error

StoreJoinResult persists the CA cert and CA-signed node cert returned by the join flow.

func VerifyNetConfig

func VerifyNetConfig(snc SignedNetConfig, pub ed25519.PublicKey) error

VerifyNetConfig checks the signature on a SignedNetConfig against pub.

func Warnf

func Warnf(format string, args ...any)

Types

type ACLRule

type ACLRule struct {
	Action     string      `json:"action"`            // "allow" or "deny" (default "allow")
	SrcPattern string      `json:"src_pat,omitempty"` // source node pattern (glob, tag:xxx, or name)
	DstPattern string      `json:"dst_pat"`           // destination node pattern
	Ports      []PortRange `json:"ports,omitempty"`   // empty = all ports
}

ACLRule defines a traffic policy. Rules are evaluated top-to-bottom; first match wins.

type ACLTable

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

ACLTable is a concurrent-safe store of node ACL policies.

func NewACLTable

func NewACLTable() *ACLTable

func (*ACLTable) Check

func (t *ACLTable) Check(callerID, destNodeID string, port uint16, lookup MetaLookup) error

Check is a convenience method on the table.

func (*ACLTable) Get

func (t *ACLTable) Get(nodeID string) NodeACL

Get returns the ACL for a node. If no explicit ACL exists, returns a default allow-all policy so nodes without ACLs are unrestricted.

func (*ACLTable) MergeFrom

func (t *ACLTable) MergeFrom(acls []NodeACL)

MergeFrom merges a slice of ACLs received via gossip.

func (*ACLTable) Snapshot

func (t *ACLTable) Snapshot() []NodeACL

Snapshot returns a copy of all ACL entries.

func (*ACLTable) Upsert

func (t *ACLTable) Upsert(a NodeACL)

Upsert adds or replaces an entry (keeps the higher Version).

type AuditEntry

type AuditEntry struct {
	Timestamp  time.Time `json:"ts"`
	Op         AuditOp   `json:"op"`
	NodeID     string    `json:"node_id,omitempty"`
	RemoteAddr string    `json:"remote_addr,omitempty"`
	Error      string    `json:"error,omitempty"`
}

AuditEntry is one line in the audit log.

type AuditLog

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

AuditLog is an append-only newline-delimited JSON file. Each Write is fsynced so no entries are lost on crash.

func OpenAuditLog

func OpenAuditLog(path string) (*AuditLog, error)

OpenAuditLog opens (or creates) the audit log at path.

func (*AuditLog) Close

func (a *AuditLog) Close() error

func (*AuditLog) ReadAll

func (a *AuditLog) ReadAll() ([]AuditEntry, error)

ReadAll returns every entry in the log.

func (*AuditLog) ReadByNode

func (a *AuditLog) ReadByNode(nodeID string) ([]AuditEntry, error)

ReadByNode returns entries for a specific node ID.

func (*AuditLog) ReadSince

func (a *AuditLog) ReadSince(t time.Time) ([]AuditEntry, error)

ReadSince returns entries at or after t.

func (*AuditLog) Write

func (a *AuditLog) Write(e AuditEntry) error

Write appends one entry to the log and fsyncs.

type AuditOp

type AuditOp string

AuditOp identifies the type of CA operation being logged.

const (
	AuditJoinAttempted AuditOp = "join_attempted"
	AuditCertIssued    AuditOp = "cert_issued"
	AuditJoinFailed    AuditOp = "join_failed"
	AuditCertRevoked   AuditOp = "cert_revoked"
)

type CA

type CA struct {
	PrivKey   ed25519.PrivateKey
	Cert      *x509.Certificate
	CertPEM   []byte
	Pool      *x509.CertPool
	JoinToken string    // legacy master token (fallback)
	Audit     *AuditLog // nil if audit logging not configured

	OnTokenUsed func(string) // callback when a token is used (wired to scribe)
	// contains filtered or unexported fields
}

CA is the certificate authority for the pulse network. Only one node runs as CA; all others get their certs signed by it.

func InitCA

func InitCA(dir string, joinToken string) (*CA, error)

InitCA generates a new CA keypair and writes it to dir.

func LoadCA

func LoadCA(dir string, joinToken string) (*CA, error)

LoadCA loads an existing CA from disk.

func (*CA) HandleJoin

func (ca *CA) HandleJoin(req JoinRequest) JoinResponse

HandleJoin validates a join request and returns the signed certificate. Authentication is token-based only.

func (*CA) IsRevoked

func (ca *CA) IsRevoked(nodeID string) bool

IsRevoked reports whether nodeID has been revoked.

func (*CA) RevokeNode

func (ca *CA) RevokeNode(nodeID string)

RevokeNode marks nodeID as revoked in the CA's local revocation set and audits it. The scribe is responsible for distributing the revocation via NetworkConfig.

func (*CA) ServerTLSConfig

func (ca *CA) ServerTLSConfig(nodeCert tls.Certificate) *tls.Config

ServerTLSConfig returns a TLS config that enforces mTLS using the CA as trust root.

func (*CA) SignIdentity

func (ca *CA) SignIdentity(pub ed25519.PublicKey, nodeID string) (JoinResponse, error)

SignIdentity issues a CA-signed certificate for the given node identity. Used by the CA node to sign its own cert during first-time initialization, so peers can verify it via mTLS using the CA pool.

func (*CA) SyncRevokedIDs

func (ca *CA) SyncRevokedIDs(ids []string)

SyncRevokedIDs updates the CA's local revocation set from a scribe NetworkConfig.

func (*CA) SyncTokens

func (ca *CA) SyncTokens(tokens []JoinToken)

SyncTokens updates the CA's local token list from a scribe NetworkConfig.

type CIDRRoute

type CIDRRoute struct {
	CIDR      string `json:"cidr"`
	NodeID    string `json:"node_id"`
	AutoLearn bool   `json:"auto,omitempty"` // true if learned from gossip, false if manually added
	// contains filtered or unexported fields
}

CIDRRoute maps a network prefix to an exit relay node. Traffic destined for IPs in CIDR is tunnelled through NodeID.

type ControlServer

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

ControlServer exposes the node's runtime over a Unix domain socket.

func NewControlServer

func NewControlServer(socketPath string, n *Node) *ControlServer

func (*ControlServer) ListenAndServe

func (s *ControlServer) ListenAndServe(ctx context.Context) error

type DNSServer

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

DNSServer resolves .pulse hostnames for the local mesh.

func NewDNSServer

func NewDNSServer(addr string, table *Table, extraZones func() []DNSZone) *DNSServer

func (*DNSServer) ListenAndServe

func (d *DNSServer) ListenAndServe(ctx context.Context) error

func (*DNSServer) ServeDNS

func (d *DNSServer) ServeDNS(w dns.ResponseWriter, r *dns.Msg)

ServeDNS handles all queries for *.pulse.

type DNSZone

type DNSZone struct {
	Name  string `json:"name"`  // fully-qualified record name, e.g. "svc.internal.example.com."
	Type  string `json:"type"`  // A, AAAA, CNAME, TXT, SRV
	Value string `json:"value"` // record value
	TTL   uint32 `json:"ttl"`
}

DNSZone is a DNS record pushed by the scribe to all node DNS servers.

type ExitRouteTable

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

ExitRouteTable is the client-side CIDR → exit node mapping. Persisted as JSON to disk so it survives restarts.

func NewExitRouteTable

func NewExitRouteTable(path string) *ExitRouteTable

func (*ExitRouteTable) Add

func (t *ExitRouteTable) Add(cidr, nodeID string) error

Add inserts a CIDR → nodeID mapping (or updates existing).

func (*ExitRouteTable) Load

func (t *ExitRouteTable) Load() error

Load reads routes from disk. No-op if the file doesn't exist yet.

func (*ExitRouteTable) Lookup

func (t *ExitRouteTable) Lookup(ip net.IP) string

Lookup returns the exit node ID for ip using longest-prefix match. Returns empty string if no route matches.

func (*ExitRouteTable) Remove

func (t *ExitRouteTable) Remove(cidr string)

Remove deletes the route for cidr.

func (*ExitRouteTable) Save

func (t *ExitRouteTable) Save() error

Save persists the current route table to disk atomically.

func (*ExitRouteTable) Snapshot

func (t *ExitRouteTable) Snapshot() []CIDRRoute

Snapshot returns a copy of the current route table for display.

func (*ExitRouteTable) SyncFromGossip

func (t *ExitRouteTable) SyncFromGossip(exitNodes []PeerEntry)

SyncFromGossip updates auto-learned routes from exit nodes in the gossip table. Manual routes are never touched. Auto-learned routes for nodes no longer advertising a CIDR are removed.

type Identity

type Identity struct {
	NodeID     string
	PublicKey  ed25519.PublicKey
	PrivateKey ed25519.PrivateKey
	TLSCert    tls.Certificate
	CAPool     *x509.CertPool // nil until joined; then used for mTLS peer verification
	Joined     bool           // true once the node has a CA-signed cert
}

func LoadOrCreateIdentity

func LoadOrCreateIdentity(dir string) (*Identity, error)

type JoinRequest

type JoinRequest struct {
	PublicKey []byte `json:"public_key"` // raw ed25519 public key of the joining node
	Token     string `json:"token"`      // shared join token
}

JoinRequest is sent by a new node to request a signed certificate.

type JoinResponse

type JoinResponse struct {
	CACert     string `json:"ca_cert"`     // PEM of the CA certificate
	SignedCert string `json:"signed_cert"` // PEM of the node's CA-signed certificate
	NodeID     string `json:"node_id"`
	Error      string `json:"error,omitempty"`
}

JoinResponse is returned by the CA (or proxied back through the mesh).

func Join

func Join(ctx context.Context, relayAddr string, req JoinRequest) (*JoinResponse, error)

Join connects to a relay's /join endpoint for first-time bootstrapping.

func SignIdentityFromKeyFile

func SignIdentityFromKeyFile(keyPath string, ca *CA) (JoinResponse, string, error)

SignIdentityFromKeyFile loads a node's identity.key and signs a cert using the given CA. Returns the JoinResponse (containing signed cert + CA cert PEM) and the node ID. Used for offline signing when the CA is behind NAT and unreachable by the new node.

type JoinToken

type JoinToken struct {
	Value     string    `json:"value"`
	CreatedAt time.Time `json:"created_at"`
	ExpiresAt time.Time `json:"expires_at,omitempty"` // zero = no expiry
	MaxUses   int       `json:"max_uses,omitempty"`   // 0 = unlimited
	UseCount  int       `json:"use_count"`
}

JoinToken is a scribe-managed token that authorizes nodes to join the mesh.

func GenerateToken

func GenerateToken(ttl time.Duration, maxUses int) JoinToken

GenerateToken creates a new random join token.

func (*JoinToken) IsExhausted

func (t *JoinToken) IsExhausted() bool

IsExhausted reports whether the token has reached its max use count.

func (*JoinToken) IsExpired

func (t *JoinToken) IsExpired() bool

IsExpired reports whether the token has passed its expiry time.

func (*JoinToken) IsValid

func (t *JoinToken) IsValid() bool

IsValid reports whether the token can still be used.

type LinkRegistry

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

LinkRegistry manages active peer sessions.

func NewLinkRegistry

func NewLinkRegistry() *LinkRegistry

func (*LinkRegistry) Add

func (r *LinkRegistry) Add(link *PeerLink)

func (*LinkRegistry) All

func (r *LinkRegistry) All() []*PeerLink

func (*LinkRegistry) Get

func (r *LinkRegistry) Get(nodeID string) (*PeerLink, bool)

func (*LinkRegistry) Has

func (r *LinkRegistry) Has(nodeID string) bool

func (*LinkRegistry) Remove

func (r *LinkRegistry) Remove(nodeID string)

func (*LinkRegistry) SessionOwner

func (r *LinkRegistry) SessionOwner(s Session) string

SessionOwner returns the NodeID of the peer that owns the given session.

type LinkStats

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

LinkStats holds measured quality metrics for a single peer link.

func (*LinkStats) LatencyMS

func (s *LinkStats) LatencyMS() float64

LatencyMS returns the exponentially-weighted moving average RTT in milliseconds. Returns math.MaxFloat64 if no successful probes yet.

func (*LinkStats) LossRate

func (s *LinkStats) LossRate() float64

LossRate returns the fraction of failed probes in the rolling window (0.0–1.0).

type LogLevel

type LogLevel int32

LogLevel controls the verbosity of pulse's logging.

const (
	LevelDebug LogLevel = iota
	LevelInfo
	LevelWarn
	LevelError
)

func ParseLogLevel

func ParseLogLevel(s string) LogLevel

ParseLogLevel maps a string to a LogLevel.

type MetaLookup

type MetaLookup func(nodeID string) NodeMeta

MetaLookup resolves a nodeID to its operator-assigned metadata.

type MultipathSession

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

MultipathSession wraps multiple Sessions to the same logical destination and provides weighted load balancing across them.

Open() uses inverse-score weighted random selection — better paths get proportionally more traffic. A 5ms path gets ~10x more streams than a 50ms path instead of an equal split.

Accept() fans in from all underlying sessions via background goroutines.

func NewMultipathSession

func NewMultipathSession(sessions []Session, scores []float64) *MultipathSession

func (*MultipathSession) Accept

func (m *MultipathSession) Accept() (net.Conn, error)

func (*MultipathSession) Close

func (m *MultipathSession) Close() error

func (*MultipathSession) IsClosed

func (m *MultipathSession) IsClosed() bool

func (*MultipathSession) Open

func (m *MultipathSession) Open() (net.Conn, error)

Open picks a session using weighted random selection (better paths get more traffic).

func (*MultipathSession) Transport

func (m *MultipathSession) Transport() string

type NATManager

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

NATManager discovers the local public address and orchestrates hole punching to build direct links between peers.

func NewNATManager

func NewNATManager(selfID string, table *Table, registry *LinkRegistry, router *Router, tlsCfg *tls.Config, onSession func(context.Context, Session, string, string)) *NATManager

func (*NATManager) HandlePunchRequest

func (m *NATManager) HandlePunchRequest(ctx context.Context, peerNodeID, peerPublicAddr, token string, punchAt time.Time)

HandlePunchRequest is called when we receive a "punch" stream from a peer. We attempt to dial the peer's public address at the scheduled time.

func (*NATManager) Run

func (m *NATManager) Run(ctx context.Context)

Run starts the periodic hole-punch loop.

type NetworkConfig

type NetworkConfig struct {
	Version    int64               `json:"version"`               // monotonically increasing (unix milliseconds)
	RevokedIDs []string            `json:"revoked_ids"`           // node IDs whose certificates have been revoked
	DNSZones   []DNSZone           `json:"dns_zones"`             // additional DNS records served by all nodes
	GlobalACLs []NodeACL           `json:"global_acls"`           // network-wide ACL additions
	NodeMeta   map[string]NodeMeta `json:"node_meta,omitempty"`   // operator-assigned node names and tags
	JoinTokens []JoinToken         `json:"join_tokens,omitempty"` // scribe-managed join tokens
}

NetworkConfig is the authoritative network-wide configuration distributed by the scribe node. Nodes merge by keeping the entry with the highest Version.

type Node

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

Node is a running relay instance.

func New

func New(cfg *config.Config, ca *CA) (*Node, error)

func (*Node) ReloadIdentity

func (n *Node) ReloadIdentity() error

listenAddr returns the address to bind listeners to. If cfg.Node.Listen is set it is used; otherwise cfg.Node.Addr. This lets nodes advertise a public IP/hostname while binding to 0.0.0.0 or a private IP. ReloadIdentity reloads the identity from disk (after a successful join).

func (*Node) Run

func (n *Node) Run(ctx context.Context) error

func (*Node) Stop

func (n *Node) Stop()

Stop triggers a graceful shutdown of the node.

type NodeACL

type NodeACL struct {
	NodeID  string    `json:"node_id"`
	Allow   []ACLRule `json:"allow"` // kept as "allow" in JSON for backward compat, but rules can be deny
	Version int64     `json:"version"`
}

NodeACL is the policy for one node. Rules are evaluated in order; first match wins.

func (NodeACL) Check

func (a NodeACL) Check(srcNodeID, destNodeID string, port uint16, lookup MetaLookup) error

Check returns nil if srcNodeID may connect to destNodeID:port. Uses first-match evaluation. No rules = allow-all (open by default). Any rules present + no match = implicit deny.

type NodeMeta

type NodeMeta struct {
	Name string   `json:"name,omitempty"`
	Tags []string `json:"tags,omitempty"`
}

NodeMeta holds operator-assigned metadata for a node (name, tags). Managed by the scribe and distributed via NetworkConfig.

type NodeStats

type NodeStats struct {
	NodeID      string    `json:"node_id"`
	ActiveConns int       `json:"active_conns"`
	BytesIn     int64     `json:"bytes_in"`
	BytesOut    int64     `json:"bytes_out"`
	ReportedAt  time.Time `json:"reported_at"`
}

NodeStats is a stats report pushed by a node to the scribe.

type PeerEntry

type PeerEntry struct {
	NodeID    string    `json:"node_id"`
	Addr      string    `json:"addr"`
	PublicKey []byte    `json:"public_key"`
	LastSeen  time.Time `json:"last_seen"`
	HopCount  int       `json:"hop_count"`
	IsCA      bool      `json:"is_ca,omitempty"`

	// Measured link quality — populated by the Prober, not gossipped.
	LatencyMS float64 `json:"latency_ms,omitempty"`
	LossRate  float64 `json:"loss_rate,omitempty"`

	// NAT hole punching.
	PublicAddr string `json:"public_addr,omitempty"`

	// Exit node routing.
	IsExit    bool     `json:"is_exit,omitempty"`
	ExitCIDRs []string `json:"exit_cidrs,omitempty"`

	// Service discovery (DNS SRV records).
	Services []ServiceRecord `json:"services,omitempty"`

	// ACL policy for this node, distributed by the CA via gossip.
	ACL *NodeACL `json:"acl,omitempty"`

	// Scribe role — collects stats and distributes NetworkConfig.
	IsScribe      bool   `json:"is_scribe,omitempty"`
	ScribeAPIAddr string `json:"scribe_api_addr,omitempty"` // HTTP API address of scribe

	// Tun device — mesh IP assigned to this node.
	MeshIP string `json:"mesh_ip,omitempty"`

	// Operator-assigned metadata (populated from NetworkConfig, not gossipped).
	Name string   `json:"name,omitempty"`
	Tags []string `json:"tags,omitempty"`
	// contains filtered or unexported fields
}

PeerEntry is a routing table record that is gossipped between nodes.

func LoadPeers

func LoadPeers(dataDir string) ([]PeerEntry, error)

LoadPeers reads peers.json from dataDir. Returns nil, nil if the file doesn't exist yet.

type PeerLink struct {
	NodeID string
	// contains filtered or unexported fields
}

PeerLink is an active session to a peer node.

func (*PeerLink) Close

func (p *PeerLink) Close() error

func (*PeerLink) IsClosed

func (p *PeerLink) IsClosed() bool

func (*PeerLink) Open

func (p *PeerLink) Open() (net.Conn, error)

func (*PeerLink) Transport

func (p *PeerLink) Transport() string

type PortRange

type PortRange struct {
	Low  uint16 `json:"low"`
	High uint16 `json:"high"` // 0 means same as Low (single port)
}

PortRange is an inclusive range of TCP ports.

func ParsePortRanges

func ParsePortRanges(s string) ([]PortRange, error)

ParsePortRanges parses a comma-separated list like "22,80,443,8000-9000".

func (PortRange) Contains

func (r PortRange) Contains(port uint16) bool

type Prober

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

Prober continuously measures link quality to all directly-connected peers.

func NewProber

func NewProber(registry *LinkRegistry, table *Table) *Prober

func (*Prober) Run

func (p *Prober) Run(ctx interface{ Done() <-chan struct{} })

Run starts the probe loop. Call in a goroutine.

type Router

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

func NewRouter

func NewRouter(table *Table, registry *LinkRegistry) *Router

func (*Router) Resolve

func (r *Router) Resolve(destNodeID string) (Session, error)

Resolve returns the best Session for reaching destNodeID. When multiple viable paths exist, a MultipathSession is returned so streams are load-balanced across all of them (Cloudflare Argo-style multipath).

type SOCKSServer

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

SOCKSServer is a SOCKS5 proxy that routes .pulse domains through the mesh and other traffic through exit nodes or directly.

func NewSOCKSServer

func NewSOCKSServer(addr string, router *Router, table *Table, exitRoutes *ExitRouteTable, selfID string, dnsZones func() []DNSZone) *SOCKSServer

func (*SOCKSServer) ListenAndServe

func (s *SOCKSServer) ListenAndServe(ctx context.Context) error

type Scribe

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

Scribe collects network-wide statistics, distributes NetworkConfig (DNS zones, revocation lists, global ACLs), and exposes an HTTP management API.

A scribe is a regular node that does not forward TCP streams — it acts as the control plane of the mesh, while relay nodes are the data plane.

func NewScribe

func NewScribe(n *Node) *Scribe

func (*Scribe) AcceptStats

func (s *Scribe) AcceptStats(stats NodeStats)

AcceptStats stores a stats report from a peer node.

func (*Scribe) AddACLRule

func (s *Scribe) AddACLRule(ctx context.Context, rule ACLRule)

AddACLRule appends a global ACL rule and broadcasts the updated config.

func (*Scribe) AddDNSZone

func (s *Scribe) AddDNSZone(ctx context.Context, zone DNSZone) error

AddDNSZone upserts a DNS zone record and broadcasts updated NetworkConfig.

func (*Scribe) CreateToken

func (s *Scribe) CreateToken(ctx context.Context, ttl time.Duration, maxUses int) JoinToken

CreateToken generates a new join token and broadcasts it to the CA.

func (*Scribe) GlobalACLRules

func (s *Scribe) GlobalACLRules() []ACLRule

GlobalACLRules returns a copy of the current global ACL rules.

func (*Scribe) IncrementTokenUse

func (s *Scribe) IncrementTokenUse(tokenValue string)

IncrementTokenUse marks a token as used once.

func (*Scribe) ListTokens

func (s *Scribe) ListTokens() []JoinToken

ListTokens returns all tokens (including expired, for display).

func (*Scribe) PushTo

func (s *Scribe) PushTo(session Session)

PushTo sends the current signed NetworkConfig to a single session. Called when a new peer connects so it gets config immediately without waiting for the next broadcast tick.

func (*Scribe) RemoveACLRule

func (s *Scribe) RemoveACLRule(ctx context.Context, index int) error

RemoveACLRule removes a global ACL rule by index and broadcasts.

func (*Scribe) RemoveDNSZone

func (s *Scribe) RemoveDNSZone(ctx context.Context, name, recType string) error

RemoveDNSZone removes DNS zone records matching name (and optionally type).

func (*Scribe) RemoveTag

func (s *Scribe) RemoveTag(ctx context.Context, nodeID, tag string)

RemoveTag removes a tag from a node.

func (*Scribe) Revoke

func (s *Scribe) Revoke(ctx context.Context, nodeID string)

Revoke adds nodeID to the revocation list and broadcasts an updated NetworkConfig.

func (*Scribe) RevokeToken

func (s *Scribe) RevokeToken(ctx context.Context, prefix string) error

RevokeToken removes a token by value prefix.

func (*Scribe) Run

func (s *Scribe) Run(ctx context.Context)

Run starts the scribe's HTTP API and the periodic NetworkConfig broadcast.

func (*Scribe) SetName

func (s *Scribe) SetName(ctx context.Context, nodeID, name string)

SetName assigns a friendly name to a node.

func (*Scribe) SetTag

func (s *Scribe) SetTag(ctx context.Context, nodeID, tag string)

SetTag adds a tag to a node.

type ServiceRecord

type ServiceRecord struct {
	Name     string `json:"name"`
	Port     uint16 `json:"port"`
	Priority uint16 `json:"priority,omitempty"`
}

ServiceRecord is a service advertised by a node in the gossip table.

type Session

type Session interface {
	// Open creates a new outbound stream to the peer.
	Open() (net.Conn, error)
	// Accept waits for the peer to open an inbound stream.
	Accept() (net.Conn, error)
	// Close terminates the session and all its streams.
	Close() error
	// IsClosed reports whether the session has been terminated.
	IsClosed() bool
	// Transport returns a human-readable transport name for logging.
	Transport() string
}

Session is an abstract multiplexed connection to a peer. Implemented by both yamuxSession (WebSocket) and quicSession (QUIC).

type SignedNetConfig

type SignedNetConfig struct {
	Config    NetworkConfig `json:"config"`
	Signature []byte        `json:"sig"`
	ScribeID  string        `json:"scribe_id"`
}

SignedNetConfig wraps a NetworkConfig with an ed25519 signature from the scribe. Nodes verify the signature against the scribe's public key from the gossip table before accepting a new config.

func SignNetConfig

func SignNetConfig(cfg NetworkConfig, priv ed25519.PrivateKey, scribeID string) (SignedNetConfig, error)

SignNetConfig signs cfg with the scribe's private key.

type Table

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

Table is a thread-safe routing table.

func NewTable

func NewTable() *Table

func (*Table) ExitNodes

func (t *Table) ExitNodes() []PeerEntry

ExitNodes returns all entries advertising themselves as exit nodes.

func (*Table) FindCA

func (t *Table) FindCA() (PeerEntry, bool)

FindCA returns the routing entry of the CA node, if known.

func (*Table) FindScribe

func (t *Table) FindScribe() (PeerEntry, bool)

FindScribe returns the routing entry of the Scribe node, if known.

func (*Table) Get

func (t *Table) Get(nodeID string) (PeerEntry, bool)

Get returns a single entry by NodeID.

func (*Table) MergeFrom

func (t *Table) MergeFrom(entries []PeerEntry, selfID string)

MergeFrom merges received entries, incrementing HopCount by 1.

func (*Table) PruneStale

func (t *Table) PruneStale(selfID string)

PruneStale removes entries whose LastSeen is older than peerStaleTTL. selfID is never pruned — the self-entry is refreshed continuously.

func (*Table) RunPruner

func (t *Table) RunPruner(ctx context.Context, selfID string)

RunPruner starts a background goroutine that periodically evicts stale peers. It stops when ctx is cancelled.

func (*Table) Snapshot

func (t *Table) Snapshot() []PeerEntry

Snapshot returns a copy of all entries.

func (*Table) SnapshotSince

func (t *Table) SnapshotSince(minVersion uint64) []PeerEntry

SnapshotSince returns entries that changed after minVersion (for delta-gossip).

func (*Table) Upsert

func (t *Table) Upsert(e PeerEntry)

Upsert adds or updates an entry, keeping the freshest LastSeen and lowest HopCount.

func (*Table) UpsertForce

func (t *Table) UpsertForce(e PeerEntry)

UpsertForce unconditionally replaces an entry, bypassing staleness checks. Use only for the local self-entry where we always want the current state to win.

func (*Table) Version

func (t *Table) Version() uint64

Version returns the current table version (monotonic counter).

type TunDevice

type TunDevice interface {
	Run(ctx context.Context)
	HandleInbound(conn net.Conn) // legacy one-shot stream (pre-pipe fallback)
	RunPipe(nodeID string, conn net.Conn)
	RefreshMeshIPs()
}

TunDevice is the interface for the optional layer-3 mesh VPN. Implemented by tunManager on Linux and tunStub elsewhere.

func NewTunDevice

func NewTunDevice(n *Node, devName, meshCIDR string) (TunDevice, error)

type TunnelRequest

type TunnelRequest struct {
	DestNodeID string `json:"dest_node"`
	DestAddr   string `json:"dest_addr"`
}

TunnelRequest describes where to route a stream.

Jump to

Keyboard shortcuts

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