ipn,wgengine/magicsock: allow setting static node endpoints via tailscaled configfile (#12882)

wgengine/magicsock,ipn: allow setting static node endpoints via tailscaled config file.

Adds a new StaticEndpoints field to tailscaled config
that can be used to statically configure the endpoints
that the node advertizes. This field will replace
TS_DEBUG_PRETENDPOINTS env var that can be used to achieve the same.

Additionally adds some functionality that ensures that endpoints
are updated when configfile is reloaded.

Also, refactor configuring/reconfiguring components to use the
same functionality when configfile is parsed the first time or
subsequent times (after reload). Previously a configfile reload
did not result in resetting of prefs. Now it does- but does not yet
tell the relevant components to consume the new prefs. This is to
be done in a follow-up.

Updates tailscale/tailscale#12578


Signed-off-by: Irbe Krumina <irbe@tailscale.com>
This commit is contained in:
Irbe Krumina
2024-07-23 18:50:55 +03:00
committed by GitHub
parent 9904421853
commit 57856fc0d5
3 changed files with 85 additions and 17 deletions

View File

@@ -14,6 +14,7 @@ import (
"io"
"net"
"net/netip"
"reflect"
"runtime"
"strconv"
"strings"
@@ -311,6 +312,12 @@ type Conn struct {
// lastEPERMRebind tracks the last time a rebind was performed
// after experiencing a syscall.EPERM.
lastEPERMRebind syncs.AtomicValue[time.Time]
// staticEndpoints are user set endpoints that this node should
// advertise amongst its wireguard endpoints. It is user's
// responsibility to ensure that traffic from these endpoints is routed
// to the node.
staticEndpoints views.Slice[netip.AddrPort]
}
// SetDebugLoggingEnabled controls whether spammy debug logging is enabled.
@@ -636,6 +643,22 @@ func (c *Conn) setEndpoints(endpoints []tailcfg.Endpoint) (changed bool) {
return true
}
// SetStaticEndpoints sets static endpoints to the provided value and triggers
// an asynchronous update of the endpoints that this node advertises.
// Static endpoints are endpoints explicitly configured by user.
func (c *Conn) SetStaticEndpoints(ep views.Slice[netip.AddrPort]) {
c.mu.Lock()
if reflect.DeepEqual(c.staticEndpoints.AsSlice(), ep.AsSlice()) {
return
}
c.staticEndpoints = ep
c.mu.Unlock()
// Technically this is not a reSTUNning, but ReSTUN does what we need at
// this point- calls updateEndpoints or queues an update if there is
// already an in-progress update.
c.ReSTUN("static-endpoint-change")
}
// setNetInfoHavePortMap updates NetInfo.HavePortMap to true.
func (c *Conn) setNetInfoHavePortMap() {
c.mu.Lock()
@@ -845,8 +868,10 @@ func (c *Conn) DiscoPublicKey() key.DiscoPublic {
return c.discoPublic
}
// determineEndpoints returns the machine's endpoint addresses. It
// does a STUN lookup (via netcheck) to determine its public address.
// determineEndpoints returns the machine's endpoint addresses. It does a STUN
// lookup (via netcheck) to determine its public address. Additionally any
// static enpoints provided by user are always added to the returned endpoints
// without validating if the node can be reached via those endpoints.
//
// c.mu must NOT be held.
func (c *Conn) determineEndpoints(ctx context.Context) ([]tailcfg.Endpoint, error) {
@@ -943,6 +968,10 @@ func (c *Conn) determineEndpoints(ctx context.Context) ([]tailcfg.Endpoint, erro
// re-run.
eps = c.endpointTracker.update(time.Now(), eps)
for i := range c.staticEndpoints.Len() {
addAddr(c.staticEndpoints.At(i), tailcfg.EndpointExplicitConf)
}
if localAddr := c.pconn4.LocalAddr(); localAddr.IP.IsUnspecified() {
ips, loopback, err := netmon.LocalAddresses()
if err != nil {
@@ -2359,6 +2388,8 @@ func (c *Conn) onPortMapChanged() { c.ReSTUN("portmap-changed") }
// ReSTUN triggers an address discovery.
// The provided why string is for debug logging only.
// If Conn.staticEndpoints have been updated, calling ReSTUN will also result in
// the new endpoints being advertised.
func (c *Conn) ReSTUN(why string) {
c.mu.Lock()
defer c.mu.Unlock()