net/udprelay: advertise addresses from cloud metadata service (#18368)
Polls IMDS (currently only AWS) for extra IPs to advertise as udprelay. Updates #17796 Change-Id: Iaaa899ef4575dc23b09a5b713ce6693f6a6a6964 Signed-off-by: Alex Valiushko <alexvaliushko@tailscale.com>
This commit is contained in:
@@ -423,7 +423,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
tailscale.com/util/cibuild from tailscale.com/health+
|
tailscale.com/util/cibuild from tailscale.com/health+
|
||||||
tailscale.com/util/clientmetric from tailscale.com/control/controlclient+
|
tailscale.com/util/clientmetric from tailscale.com/control/controlclient+
|
||||||
tailscale.com/util/cloudenv from tailscale.com/net/dns/resolver+
|
tailscale.com/util/cloudenv from tailscale.com/net/dns/resolver+
|
||||||
tailscale.com/util/cloudinfo from tailscale.com/wgengine/magicsock
|
tailscale.com/util/cloudinfo from tailscale.com/wgengine/magicsock+
|
||||||
tailscale.com/util/cmpver from tailscale.com/net/dns+
|
tailscale.com/util/cmpver from tailscale.com/net/dns+
|
||||||
tailscale.com/util/ctxkey from tailscale.com/ipn/ipnlocal+
|
tailscale.com/util/ctxkey from tailscale.com/ipn/ipnlocal+
|
||||||
💣 tailscale.com/util/deephash from tailscale.com/util/syspolicy/setting
|
💣 tailscale.com/util/deephash from tailscale.com/util/syspolicy/setting
|
||||||
|
|||||||
+24
-4
@@ -43,6 +43,7 @@ import (
|
|||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
"tailscale.com/types/nettype"
|
"tailscale.com/types/nettype"
|
||||||
"tailscale.com/types/views"
|
"tailscale.com/types/views"
|
||||||
|
"tailscale.com/util/cloudinfo"
|
||||||
"tailscale.com/util/eventbus"
|
"tailscale.com/util/eventbus"
|
||||||
"tailscale.com/util/set"
|
"tailscale.com/util/set"
|
||||||
"tailscale.com/util/usermetric"
|
"tailscale.com/util/usermetric"
|
||||||
@@ -81,6 +82,7 @@ type Server struct {
|
|||||||
netChecker *netcheck.Client
|
netChecker *netcheck.Client
|
||||||
metrics *metrics
|
metrics *metrics
|
||||||
netMon *netmon.Monitor
|
netMon *netmon.Monitor
|
||||||
|
cloudInfo *cloudinfo.CloudInfo // used to query cloud metadata services
|
||||||
|
|
||||||
mu sync.Mutex // guards the following fields
|
mu sync.Mutex // guards the following fields
|
||||||
macSecrets views.Slice[[blake2s.Size]byte] // [0] is most recent, max 2 elements
|
macSecrets views.Slice[[blake2s.Size]byte] // [0] is most recent, max 2 elements
|
||||||
@@ -336,6 +338,7 @@ func NewServer(logf logger.Logf, port uint16, onlyStaticAddrPorts bool, metrics
|
|||||||
onlyStaticAddrPorts: onlyStaticAddrPorts,
|
onlyStaticAddrPorts: onlyStaticAddrPorts,
|
||||||
serverEndpointByDisco: make(map[key.SortedPairOfDiscoPublic]*serverEndpoint),
|
serverEndpointByDisco: make(map[key.SortedPairOfDiscoPublic]*serverEndpoint),
|
||||||
nextVNI: minVNI,
|
nextVNI: minVNI,
|
||||||
|
cloudInfo: cloudinfo.New(logf),
|
||||||
}
|
}
|
||||||
s.discoPublic = s.disco.Public()
|
s.discoPublic = s.disco.Public()
|
||||||
s.metrics = registerMetrics(metrics)
|
s.metrics = registerMetrics(metrics)
|
||||||
@@ -402,11 +405,13 @@ func (s *Server) startPacketReaders() {
|
|||||||
|
|
||||||
func (s *Server) addrDiscoveryLoop() {
|
func (s *Server) addrDiscoveryLoop() {
|
||||||
defer s.wg.Done()
|
defer s.wg.Done()
|
||||||
|
|
||||||
timer := time.NewTimer(0) // fire immediately
|
timer := time.NewTimer(0) // fire immediately
|
||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
|
|
||||||
getAddrPorts := func() ([]netip.AddrPort, error) {
|
getAddrPorts := func() ([]netip.AddrPort, error) {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
var addrPorts set.Set[netip.AddrPort]
|
var addrPorts set.Set[netip.AddrPort]
|
||||||
addrPorts.Make()
|
addrPorts.Make()
|
||||||
|
|
||||||
@@ -425,6 +430,21 @@ func (s *Server) addrDiscoveryLoop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get cloud metadata service addresses.
|
||||||
|
// TODO(illotum) Same is done within magicsock, consider caching within cloudInfo
|
||||||
|
cloudIPs, err := s.cloudInfo.GetPublicIPs(ctx)
|
||||||
|
if err == nil { // Not handling the err, GetPublicIPs already printed to log.
|
||||||
|
for _, ip := range cloudIPs {
|
||||||
|
if ip.IsValid() {
|
||||||
|
if ip.Is4() {
|
||||||
|
addrPorts.Add(netip.AddrPortFrom(ip, s.uc4Port))
|
||||||
|
} else {
|
||||||
|
addrPorts.Add(netip.AddrPortFrom(ip, s.uc6Port))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dm := s.getDERPMap()
|
dm := s.getDERPMap()
|
||||||
if dm == nil {
|
if dm == nil {
|
||||||
// We don't have a DERPMap which is required to dynamically
|
// We don't have a DERPMap which is required to dynamically
|
||||||
@@ -434,9 +454,7 @@ func (s *Server) addrDiscoveryLoop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get addrPorts as visible from DERP
|
// get addrPorts as visible from DERP
|
||||||
netCheckerCtx, netCheckerCancel := context.WithTimeout(context.Background(), netcheck.ReportTimeout)
|
rep, err := s.netChecker.GetReport(ctx, dm, &netcheck.GetReportOpts{
|
||||||
defer netCheckerCancel()
|
|
||||||
rep, err := s.netChecker.GetReport(netCheckerCtx, dm, &netcheck.GetReportOpts{
|
|
||||||
OnlySTUN: true,
|
OnlySTUN: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -474,6 +492,8 @@ func (s *Server) addrDiscoveryLoop() {
|
|||||||
// Mirror magicsock behavior for duration between STUN. We consider
|
// Mirror magicsock behavior for duration between STUN. We consider
|
||||||
// 30s a min bound for NAT timeout.
|
// 30s a min bound for NAT timeout.
|
||||||
timer.Reset(tstime.RandomDurationBetween(20*time.Second, 26*time.Second))
|
timer.Reset(tstime.RandomDurationBetween(20*time.Second, 26*time.Second))
|
||||||
|
// TODO(illotum) Pass in context bound to the [s.closeCh] lifetime,
|
||||||
|
// and do not block on getAddrPorts IO.
|
||||||
addrPorts, err := getAddrPorts()
|
addrPorts, err := getAddrPorts()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logf("error discovering IP:port candidates: %v", err)
|
s.logf("error discovering IP:port candidates: %v", err)
|
||||||
|
|||||||
Reference in New Issue
Block a user