Adopt the predecessor's tunnel in place: its range, its address, its peers
On an adopted hub the private network takes over the tunnel it finds rather than running beside it (hq ADR 0105): two tunnels leave the mesh's unreachable through the provider's filter, so no machine can ever join. The node presents the found tunnel when it enrols, under the key it took as its own; the inventory records it (node.tunnel, tunnel_peer — migration 0031) and the mesh composes from it: the overlay's range is the adopted tunnel's, the hub is placed at the tunnel's address on the tunnel's port, and every peer the tunnel had is carried in the hub's peer list as a peer of the tunnel, not a node of the mesh, until a node enrols with that key — which then keeps the address the tunnel had for it. A fresh node never gets an address the tunnel holds. The hub's declaration tells the host which unit to take over; the host's account of carrying it is recorded and shown. Every reader of the range follows the setting; nothing stores it. A found tunnel under another key is recorded and not adopted, so ADR 0100's non-overlap rule keeps applying where a tunnel is left running beside the mesh's. A lab bed and test skeleton for "How it is checked" are under lab/.
This commit is contained in:
@@ -124,6 +124,29 @@ func (e Enrolment) Enrol(ctx context.Context, request EnrolRequest) (reply Enrol
|
||||
"%s's overlay key could not be recorded: %w", node.Name, err)
|
||||
}
|
||||
}
|
||||
// And the tunnel it found, whose key is the overlay key above (novox/hq ADR 0105). Recorded
|
||||
// before the token is spent for the same reason as the keys: the first declaration this node
|
||||
// receives is composed from it, and a hub enrolled without its tunnel would be placed at an
|
||||
// address of the mesh's choosing rather than the tunnel's.
|
||||
if request.Tunnel != nil {
|
||||
if request.Tunnel.PublicKey != request.OverlayKey {
|
||||
return EnrolReply{}, fmt.Errorf("%s presented a tunnel under key %s and an overlay key "+
|
||||
"that is not it; a tunnel is taken over with its own key or not at all", node.Name,
|
||||
request.Tunnel.PublicKey)
|
||||
}
|
||||
peers := make([]inventory.TunnelPeer, 0, len(request.Tunnel.Peers))
|
||||
for _, p := range request.Tunnel.Peers {
|
||||
peers = append(peers, inventory.TunnelPeer{PublicKey: p.PublicKey, Address: p.Address})
|
||||
}
|
||||
if err := e.Inventory.RecordTunnel(ctx, node.ID, inventory.Tunnel{
|
||||
Interface: request.Tunnel.Interface, Unit: request.Tunnel.Unit,
|
||||
Config: request.Tunnel.Config, Port: request.Tunnel.Port,
|
||||
Address: request.Tunnel.Address, Range: request.Tunnel.Range,
|
||||
PublicKey: request.Tunnel.PublicKey, Peers: peers,
|
||||
}); err != nil {
|
||||
return EnrolReply{}, fmt.Errorf("%s's found tunnel could not be recorded: %w", node.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Spent once the node is complete in the store.
|
||||
if err := e.Inventory.Spend(ctx, secret, by); err != nil {
|
||||
@@ -219,6 +242,15 @@ func (e Enrolment) Heard(ctx context.Context, report Report) (err error) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// What it says about the tunnel it carried (novox/hq ADR 0105), whenever it says it.
|
||||
if report.Tunnel != nil {
|
||||
if err := e.Inventory.RecordCarriedTunnel(ctx, node.ID, inventory.Carried{
|
||||
Interface: report.Tunnel.Interface, Port: report.Tunnel.Port, Range: report.Tunnel.Range,
|
||||
Peers: report.Tunnel.Peers, Taken: report.Tunnel.Taken, Kept: report.Tunnel.Kept,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// A bare word that a node is there is not an account of what the machine did or holds: it
|
||||
// moves last_seen and touches nothing else. This arrives every minute (link.AliveEvery),
|
||||
|
||||
@@ -71,12 +71,39 @@ type EnrolRequest struct {
|
||||
// node's public key could replay the spent token (novox/hq issue 083, on review).
|
||||
Proof []byte `json:"proof,omitempty"`
|
||||
|
||||
// Tunnel is the tunnel this node found on its machine and whose key it took as its overlay
|
||||
// key (novox/hq ADR 0105): the interface, its port, address and range, and its peers. Presented
|
||||
// with the keys because it is one of them — OverlayKey above is this tunnel's public key when
|
||||
// it is set — and the mesh composes the hub's address, the range and every carried peer from
|
||||
// it. Nil from a node that found none, which is every converged one.
|
||||
Tunnel *Tunnel `json:"tunnel,omitempty"`
|
||||
|
||||
// Redelivered is set by the control plane, never sent: the broker handed this request over a
|
||||
// second time. Such a request does not finish an enrolment already spent — the first time may
|
||||
// have answered, and the node holds what it was told.
|
||||
Redelivered bool `json:"-"`
|
||||
}
|
||||
|
||||
// Tunnel is a found tunnel as a node presents it: everything but its private key, which the node
|
||||
// keeps as its own overlay key and never sends.
|
||||
type Tunnel struct {
|
||||
Interface string `json:"interface"`
|
||||
Unit string `json:"unit"`
|
||||
Config string `json:"config"`
|
||||
Port int `json:"port"`
|
||||
Address string `json:"address"`
|
||||
Range string `json:"range"`
|
||||
PublicKey string `json:"public_key"`
|
||||
Peers []TunnelPeer `json:"peers,omitempty"`
|
||||
}
|
||||
|
||||
// TunnelPeer is one peer of a found tunnel: its public key and the address the tunnel routed to
|
||||
// it.
|
||||
type TunnelPeer struct {
|
||||
PublicKey string `json:"public_key"`
|
||||
Address string `json:"address"`
|
||||
}
|
||||
|
||||
// Signed is a declaration and the signature over it.
|
||||
//
|
||||
// The signature is over Declaration exactly as it will arrive, bytes unchanged — a node verifies
|
||||
@@ -129,6 +156,21 @@ type Report struct {
|
||||
// Reachable is what can be reached on the machine now: every listening socket and every
|
||||
// published container port. Only an adopted node reports it; it is what converging previews.
|
||||
Reachable []Reach `json:"reachable,omitempty"`
|
||||
|
||||
// Tunnel is what an adopted node says about the tunnel it found and carried (novox/hq ADR
|
||||
// 0105): the interface, its port, range and peer count, whether the found interface is down
|
||||
// and the mesh's up in its place, and where the found configuration's original was kept.
|
||||
Tunnel *CarriedTunnel `json:"tunnel,omitempty"`
|
||||
}
|
||||
|
||||
// CarriedTunnel is a node's account of the tunnel it took over.
|
||||
type CarriedTunnel struct {
|
||||
Interface string `json:"interface"`
|
||||
Port int `json:"port"`
|
||||
Range string `json:"range"`
|
||||
Peers int `json:"peers"`
|
||||
Taken bool `json:"taken"`
|
||||
Kept string `json:"kept,omitempty"`
|
||||
}
|
||||
|
||||
// Held is one file or container found on an adopted node and kept as it was.
|
||||
|
||||
Reference in New Issue
Block a user