Skip to content

Releases: pg83/mesh

33

Choose a tag to compare

@github-actions github-actions released this 18 Sep 07:03

Full Changelog: 32...33

32

32

Choose a tag to compare

@pg83 pg83 released this 16 Sep 17:23

The web interface now uses English throughout. Remove the Springs view and the introductory banner from the configuration page.

Consolidate each Go type and its methods in one file and standardize compound file names.

31

31

Choose a tag to compare

@pg83 pg83 released this 16 Sep 14:25

Move the existing web navigation from the top bar into a left panel, preserving the graph, inspector and controls.

Add configurable DNS pools within the .mesh zone: "*.lab": ["lab1", "lab2", "lab3"] under dns_records answers names such as grafana.lab.mesh with all distinct reachable mesh addresses in shuffled order. Pools use the current registry and local routes, include relay paths, and have a five-second TTL. Embedded and standalone DNS share the rules; standalone DNS rejects stale control data.

Compatible with 30. DNS pools are optional and require configuration.

Built and published manually. Linux web, DNS, registry-discovery, status and no-TUN end-to-end checks passed; the sidebar was also checked in Chromium at desktop and mobile sizes.

30

30

Choose a tag to compare

@pg83 pg83 released this 16 Sep 10:20

A node is alive while some live node hears it, the closure of the node's own observations: two nodes that heard each other and left together no longer keep each other routable, and the addresses in a node's graph record are dialed only while it is alive. Static registry endpoints are dialed always. The status carries the live set, the metrics a mesh_peer_alive gauge, the web page marks a node nobody hears.

The graph rebuilds once a second, on the ticker alone: no more 20 ms recompute whenever a channel reported or a record arrived. A channel starts from the last snapshot and has no ticker of its own; its reports, gossip, registry exchange and silence check follow the snapshot. The incoming UDP reader no longer blocks its socket while a new channel is installed.

A datagram the kernel refuses is a lost datagram: the UDP channel keeps its socket, only silence takes the link down. This ends the redial loop on macOS, where sendto to an absent host fails synchronously.

Compatible with 29.

29

29

Choose a tag to compare

@pg83 pg83 released this 15 Sep 19:58

Exit nodes and subnet routes: a node with exit: true (or -exit) carries traffic for networks beyond the mesh, and a client lists in routes which prefixes go to which exits; the prefixes are routed into its TUN device and each flow keeps its exit. The exit's system forwards and, for the internet, NATs.

A node runs without a TUN device with -no-tun, and by default when started with -sshd; -tun or a tun name in the config keeps the device. Such a node relays and serves SSH and DNS to peers.

A node is reachable only while some node observes a link from it; the last record of a node that went away no longer keeps a route into it.

Graph records carry a flags byte: nodes on releases before 29 exchange no graph records with this release; update peers together.

28

28

Choose a tag to compare

@pg83 pg83 released this 15 Sep 16:07

Names: every registry entry with a name is <name>.mesh. With dns: true (or -dns) the node answers the zone from its own registry, on its mesh address for peers and on the subnet's service address, the first address of the subnet, for its own system; mesh dns serves the same zone from the control API on a plain socket. A and PTR records, empty answers for other types, NXDOMAIN inside the zone, REFUSED outside it, so a resolver forwards only the zone.

Failed WebSocket connection attempts back off exponentially up to a minute; a new interface address, a link from the peer or a new record of it retries at once. Status reports how many packets the version bundle takes and carries the subnet.

Compatible with 27.

27

27

Choose a tag to compare

@pg83 pg83 released this 15 Sep 12:58

Gossip sends a record to a peer only until the peer's version vector shows it: every node publishes the versions of the records it holds, vectors travel through the mesh like records, and each second a channel carries one small compressed bundle of vectors instead of every record. A peer whose vector never arrives still gets everything every second. Records and bundles are zstd frames.

Routes are chosen by link cost with Dijkstra: UDP beats WebSocket on the same pair, equal costs prefer fewer hops. A WebSocket connection that receives nothing for five seconds, or fails a read or write, closes as a whole and is redialed at once instead of after the kernel's TCP timeout. A node dials a target only from the interface whose network contains it or through which the system routes it. Status exports routes to peers only.

The embedded SSH server delivers the output still in the pty when a command exits, and the web page shows only endpoints linked to other nodes.

Nodes on releases before 27 exchange no graph records with this release; update peers together.

26

26

Choose a tag to compare

@pg83 pg83 released this 14 Sep 19:15

The web UI gets a spring simulation view: hosts carry a large charge and repel everything, endpoint circles a small one, every edge is a spring, and the layout animates until the bodies stop. Sliders adjust the host charge, the link length and the damping; restart and shake buttons perturb the system; dragged nodes stay pinned while held.

Compatible with 24 and 25.

25

25

Choose a tag to compare

@pg83 pg83 released this 14 Sep 18:52

The web endpoint graph shows only vertices linked to another node; listeners nobody links into and sources without an observed link no longer hang off their host as lone circles.

The embedded SSH server guards the session pty and process between the request loop and the wait goroutine, fixing a race between a window-change request and the pty closing after the command exits.

Compatible with 24.

24

24

Choose a tag to compare

@pg83 pg83 released this 14 Sep 17:14

Graph vertices are 32-bit ids: the owner's registry index in the high byte and a counter below it. Counter 0 is the node's mesh-IP vertex, registry endpoints take the following counters in registry order, and runtime vertices (implicit listeners, one source per connection attempt) are allocated from 1024. Descriptions travel only in the owner's graph record; packets carry a 4-byte source id and routing works in ids alone.

Outgoing UDP leaves the node's listener socket on its interface, so a forwarded listener's traffic uses its forwarded mapping. Every interface address without a configured UDP listener gets an implicit socket advertised like a listener. Nodes report next to each incoming UDP link the wire address the packets actually arrive from, and a node dialing a private listener off its own networks sends to that observed NAT mapping, so two nodes behind cone NAT connect directly through any common peer without STUN or coordination messages.

The nonce is no longer sent: packet ids come from one counter per node started from the clock, and the id word doubles as the nonce. The header is 9 bytes, with the packet kind in the low bits of the id word and the sender index in one byte; the inner data byte holds hop count and cursor.

Nodes on releases before 24 cannot exchange any packets with this release; update peers together.