cmd/lopower: force AAAA records in DNS server

Change-Id: I79582e4ffd468c217df3e8c02bbf65d911a4f0fe
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick 2024-11-03 11:52:50 -08:00 committed by Anton Tolchanov
parent 89d042d6e5
commit ddc5d14d09
6 changed files with 46 additions and 10 deletions

View File

@ -623,14 +623,19 @@ func (lp *lpServer) startTSNet(ctx context.Context) {
log.Fatal(err)
}
lp.tsnet = &tsnet.Server{
ts := &tsnet.Server{
Dir: filepath.Join(lp.dir, "tsnet"),
Hostname: hostname,
UserLogf: log.Printf,
Ephemeral: false,
}
lp.tsnet = ts
ts.PreStart = func() error {
ts.Sys().DNSManager.Get().SetForceAAAA(true)
return nil
}
if _, err := lp.tsnet.Up(ctx); err != nil {
if _, err := ts.Up(ctx); err != nil {
log.Fatal(err)
}
}

View File

@ -352,7 +352,7 @@ func TestDNSConfigForNetmap(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
verOS := cmp.Or(tt.os, "linux")
var log tstest.MemLogger
got := dnsConfigForNetmap(tt.nm, peersMap(tt.peers), tt.prefs.View(), tt.expired, log.Logf, verOS)
got := dnsConfigForNetmap(tt.nm, peersMap(tt.peers), tt.prefs.View(), tt.expired, false, log.Logf, verOS)
if !reflect.DeepEqual(got, tt.want) {
gotj, _ := json.MarshalIndent(got, "", "\t")
wantj, _ := json.MarshalIndent(tt.want, "", "\t")

View File

@ -4911,7 +4911,13 @@ func (b *LocalBackend) authReconfig() {
disableSubnetsIfPAC := cn.SelfHasCap(tailcfg.NodeAttrDisableSubnetsIfPAC)
userDialUseRoutes := cn.SelfHasCap(tailcfg.NodeAttrUserDialUseRoutes)
dohURL, dohURLOK := cn.exitNodeCanProxyDNS(prefs.ExitNodeID())
dcfg := cn.dnsConfigForNetmap(prefs, b.keyExpired, b.logf, version.OS())
var forceAAAA bool
if dm, ok := b.sys.DNSManager.GetOK(); ok {
forceAAAA = dm.GetForceAAAA()
}
dcfg := cn.dnsConfigForNetmap(prefs, b.keyExpired, forceAAAA, b.logf, version.OS())
// If the current node is an app connector, ensure the app connector machine is started
b.reconfigAppConnectorLocked(nm, prefs)
closing := b.shutdownCalled
@ -5018,10 +5024,10 @@ func shouldUseOneCGNATRoute(logf logger.Logf, mon *netmon.Monitor, controlKnobs
return false
}
func (nb *nodeBackend) dnsConfigForNetmap(prefs ipn.PrefsView, selfExpired bool, logf logger.Logf, versionOS string) *dns.Config {
func (nb *nodeBackend) dnsConfigForNetmap(prefs ipn.PrefsView, selfExpired, forceAAAA bool, logf logger.Logf, versionOS string) *dns.Config {
nb.mu.Lock()
defer nb.mu.Unlock()
return dnsConfigForNetmap(nb.netMap, nb.peers, prefs, selfExpired, logf, versionOS)
return dnsConfigForNetmap(nb.netMap, nb.peers, prefs, selfExpired, forceAAAA, logf, versionOS)
}
// dnsConfigForNetmap returns a *dns.Config for the given netmap,
@ -5029,7 +5035,7 @@ func (nb *nodeBackend) dnsConfigForNetmap(prefs ipn.PrefsView, selfExpired bool,
//
// The versionOS is a Tailscale-style version ("iOS", "macOS") and not
// a runtime.GOOS.
func dnsConfigForNetmap(nm *netmap.NetworkMap, peers map[tailcfg.NodeID]tailcfg.NodeView, prefs ipn.PrefsView, selfExpired bool, logf logger.Logf, versionOS string) *dns.Config {
func dnsConfigForNetmap(nm *netmap.NetworkMap, peers map[tailcfg.NodeID]tailcfg.NodeView, prefs ipn.PrefsView, selfExpired, forceAAAA bool, logf logger.Logf, versionOS string) *dns.Config {
if nm == nil {
return nil
}
@ -5092,7 +5098,7 @@ func dnsConfigForNetmap(nm *netmap.NetworkMap, peers map[tailcfg.NodeID]tailcfg.
// https://github.com/tailscale/tailscale/issues/1152
// tracks adding the right capability reporting to
// enable AAAA in MagicDNS.
if addr.Addr().Is6() && have4 {
if addr.Addr().Is6() && have4 && !forceAAAA {
continue
}
ips = append(ips, addr.Addr())

View File

@ -1253,7 +1253,7 @@ func TestDNSConfigForNetmapForExitNodeConfigs(t *testing.T) {
}
prefs := &ipn.Prefs{ExitNodeID: tc.exitNode, CorpDNS: true}
got := dnsConfigForNetmap(nm, peersMap(tc.peers), prefs.View(), false, t.Logf, "")
got := dnsConfigForNetmap(nm, peersMap(tc.peers), prefs.View(), false, false, t.Logf, "")
if !resolversEqual(t, got.DefaultResolvers, tc.wantDefaultResolvers) {
t.Errorf("DefaultResolvers: got %#v, want %#v", got.DefaultResolvers, tc.wantDefaultResolvers)
}

View File

@ -66,7 +66,8 @@ type Manager struct {
mu sync.Mutex // guards following
// config is the last configuration we successfully compiled or nil if there
// was any failure applying the last configuration.
config *Config
config *Config
forceAAAA bool // whether client wants MagicDNS AAAA even if unsure of host's IPv6 status
}
// NewManagers created a new manager from the given config.
@ -148,6 +149,18 @@ func (m *Manager) GetBaseConfig() (OSConfig, error) {
return m.os.GetBaseConfig()
}
func (m *Manager) GetForceAAAA() bool {
m.mu.Lock()
defer m.mu.Unlock()
return m.forceAAAA
}
func (m *Manager) SetForceAAAA(v bool) {
m.mu.Lock()
defer m.mu.Unlock()
m.forceAAAA = v
}
// setLocked sets the DNS configuration.
//
// m.mu must be held.

View File

@ -125,6 +125,11 @@ type Server struct {
// field at zero unless you know what you are doing.
Port uint16
// PreStart is an optional hook to run just before LocalBackend.Start,
// to reconfigure internals. If it returns an error, Server.Start
// will return that error, wrapper.
PreStart func() error
getCertForTesting func(*tls.ClientHelloInfo) (*tls.Certificate, error)
initOnce sync.Once
@ -664,6 +669,13 @@ func (s *Server) start() (reterr error) {
prefs.ControlURL = s.ControlURL
prefs.RunWebClient = s.RunWebClient
authKey := s.getAuthKey()
if f := s.PreStart; f != nil {
if err := f(); err != nil {
return fmt.Errorf("PreStart: %w", err)
}
}
err = lb.Start(ipn.Options{
UpdatePrefs: prefs,
AuthKey: authKey,