mirror of
https://github.com/juanfont/headscale.git
synced 2026-10-06 06:40:06 +09:00
mapper: drop DNSConfig from policy responses
It forced every client into a full netmap rebuild; the resolver race it guarded against was a client bug (tailscale/tailscale#19749).
This commit is contained in:
committed by
Kristoffer Dalby
parent
357f34a778
commit
eeaac680be
@@ -2446,3 +2446,28 @@ func TestHandleNodeChangeRetryAfterRemoval(t *testing.T) {
|
||||
assert.Empty(t, sent[1].PeersRemoved)
|
||||
assert.NotEmpty(t, sent[1].PacketFilters)
|
||||
}
|
||||
|
||||
// TestDNSConfigOnlyWithSelfRefresh checks policy responses leave DNSConfig
|
||||
// out, which clients read as unchanged, while self refreshes carry it: a
|
||||
// node's DNS config derives from its own CapMap and Hostinfo, and a
|
||||
// DNSConfig forces clients into a full netmap rebuild.
|
||||
func TestDNSConfigOnlyWithSelfRefresh(t *testing.T) {
|
||||
testData, cleanup := setupBatcherWithTestData(t, NewBatcherAndMapper, 1, 2, normalBufferSize)
|
||||
defer cleanup()
|
||||
|
||||
testData.Config.TailcfgDNSConfig = &tailcfg.DNSConfig{
|
||||
Proxied: true,
|
||||
Domains: []string{"headscale.test"},
|
||||
}
|
||||
|
||||
self := testData.Nodes[0].n.ID
|
||||
mc := newMockNodeConnection(self)
|
||||
|
||||
require.NoError(t, handleNodeChange(mc, testData.Batcher.mapper, change.PolicyChange()))
|
||||
require.NoError(t, handleNodeChange(mc, testData.Batcher.mapper, change.SelfUpdate(self)))
|
||||
|
||||
sent := mc.getSent()
|
||||
require.Len(t, sent, 2)
|
||||
assert.Nil(t, sent[0].DNSConfig, "policy response must not carry DNSConfig")
|
||||
assert.NotNil(t, sent[1].DNSConfig, "self refresh must carry DNSConfig")
|
||||
}
|
||||
|
||||
@@ -309,14 +309,12 @@ func (m *mapper) selfMapResponse(
|
||||
// - PeersChanged for remaining peers (their AllowedIPs may have changed due to policy)
|
||||
// - Updated PacketFilters
|
||||
// - Updated SSHPolicy (SSH rules may reference users/groups that changed)
|
||||
// - DNSConfig so the client's resolver state stays anchored even when a
|
||||
// policy-triggered wgengine reconfigure races a netmon LinkChange (the
|
||||
// LinkChange handler reapplies dns.Manager.Set with the engine's
|
||||
// lastDNSConfig; if that snapshot is stale, the OS resolver loses the
|
||||
// MagicDNS reverse-DNS routes and Nameservers and curl-by-FQDN stops
|
||||
// resolving for the rest of the policy window).
|
||||
// - Optionally, the node's own self info (when includeSelf is true)
|
||||
//
|
||||
// DNSConfig is left out: it forces clients into a full netmap rebuild, and
|
||||
// the node's DNS config inputs arrive with its own [change.SelfUpdate], see
|
||||
// [state.State.DrainSelfRefreshes].
|
||||
//
|
||||
// This avoids the issue where an empty Peers slice is interpreted by Tailscale
|
||||
// clients as "no change" rather than "no peers".
|
||||
// When includeSelf is true, the node's self info is included so that a node
|
||||
@@ -331,7 +329,6 @@ func (m *mapper) policyChangeResponse(
|
||||
builder := m.NewMapResponseBuilder(nodeID).
|
||||
WithDebugType(policyResponseDebug).
|
||||
WithCapabilityVersion(capVer).
|
||||
WithDNSConfig().
|
||||
WithPacketFilters().
|
||||
WithSSHPolicy()
|
||||
|
||||
|
||||
@@ -477,6 +477,7 @@ func firstResolver(nm *netmap.NetworkMap) string {
|
||||
// TestNodeAttrsNextDNS checks a node's DNS config follows each of its
|
||||
// inputs: the NextDNS profile from nodeAttrs, whether reached through a
|
||||
// policy reload or a tag change, and the device metadata from its Hostinfo.
|
||||
// Policy responses do not carry DNSConfig, so each must arrive on its own.
|
||||
func TestNodeAttrsNextDNS(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user