Documentation
¶
Overview ¶
Package coordinator is the harness's side of the Tailscale coordination protocol: ts2021, Noise inside a WebSocket at /ts2021, the one upgrade the tunnel passes. A worker registers with its join secret and gets an address in the project's /48 and a name. The harness's own node registers the same way, on loopback, with a secret only this process holds. Then each node long-polls a map of the nodes it may reach and of the relay. The nodes are in nodes.json in the harness's directory.
The protocol handling is copied from headscale's hscontrol (see LICENSE) and trimmed to register, map, keepalive, deltas and ephemeral expiry: no database, CLI, OIDC, policy language, DNS, routes, SSH or Taildrop.
Index ¶
- type Coordinator
- func (c *Coordinator) Check(name string, d Drive) (string, error)
- func (c *Coordinator) Desired(name string) worker.Desired
- func (c *Coordinator) Handle(mux *http.ServeMux)
- func (c *Coordinator) Known(k key.NodePublic) bool
- func (c *Coordinator) Link(pairs [][2]string)
- func (c *Coordinator) Listen(ctx context.Context, dir, control string, ports ...int) ([]net.Listener, error)
- func (c *Coordinator) Node(a netip.Addr) (string, bool)
- func (c *Coordinator) Public() key.MachinePublic
- func (c *Coordinator) Relay(u string)
- func (c *Coordinator) Remove(name string) error
- func (c *Coordinator) SetDrives(ds map[string]Drive) []error
- type Drive
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Coordinator ¶
type Coordinator struct {
// Gone hangs up on the worker named name once its node left or expired:
// a node that logged out sends no FIN after, and the harness would hold
// its connection for minutes. Set before Handle.
Gone func(name string)
// contains filtered or unexported fields
}
Coordinator holds the nodes of one project.
func New ¶
func New(dir string, secret []byte, join func(secret, addr string) (string, error)) (*Coordinator, error)
New loads the Noise key and the nodes from dir, made there the first time. secret is the harness key. join checks a join secret sent from addr and returns the reserved name it gives the node, worker.Admin or none. Each ephemeral node loaded has idle from now to poll again.
func (*Coordinator) Check ¶ added in v0.5.5
func (c *Coordinator) Check(name string, d Drive) (string, error)
Check is the name of the server drive d, named name, would have, or why it would have none.
func (*Coordinator) Desired ¶ added in v0.5.0
func (c *Coordinator) Desired(name string) worker.Desired
Desired is what the worker named name should serve, to which addresses, and mount, from where: the access rule again, for the file servers.
func (*Coordinator) Handle ¶
func (c *Coordinator) Handle(mux *http.ServeMux)
Handle serves the Noise key at /key and the protocol at /ts2021 on mux.
func (*Coordinator) Known ¶
func (c *Coordinator) Known(k key.NodePublic) bool
Known is whether k is a registered node's. The relay admits no other.
func (*Coordinator) Link ¶ added in v0.4.0
func (c *Coordinator) Link(pairs [][2]string)
Link makes each pair of workers, by name, see each other, and no others, and wakes every map poll to send the change.
func (*Coordinator) Listen ¶
func (c *Coordinator) Listen(ctx context.Context, dir, control string, ports ...int) ([]net.Listener, error)
Listen puts the harness on its own mesh as a node in userspace, no TUN and no root, with its keys in dir so its address holds across restarts. It registers at control, this coordinator on loopback, so it needs neither the tunnel nor a proof, with the secret only this process holds, and is named worker.Harness. There is a listener for each port on the node's address, which only nodes the coordinator gave keys to can reach. It all closes when ctx ends.
func (*Coordinator) Node ¶
func (c *Coordinator) Node(a netip.Addr) (string, bool)
Node is the name of the registered node at address a.
func (*Coordinator) Public ¶
func (c *Coordinator) Public() key.MachinePublic
Public is the Noise key workers fetch at /key. The harness key vouches for it in /id, because TLS ends at the tunnel.
func (*Coordinator) Relay ¶
func (c *Coordinator) Relay(u string)
Relay puts the relay at the host of the harness's URL u in every node's map.
func (*Coordinator) Remove ¶
func (c *Coordinator) Remove(name string) error
Remove takes the worker named name off the mesh for good. Its poll ends and peers drop it at once. Its next poll finds it no longer authorized, which its worker takes as the word to leave. Its keys stay refused; the same machine joins again only with new keys, as a new install makes.