net/dns,net/dns/resolver: refactor channels/magicDNS out of Resolver

Moves magicDNS-specific handling out of Resolver & into dns.Manager. This
greatly simplifies the Resolver to solely issuing queries and returning
responses, without channels.

Enforcement of max number of in-flight magicDNS queries, assembly of
synthetic UDP datagrams, and integration with wgengine for
recieving/responding to magicDNS traffic is now entirely in Manager.
This path is being kept around, but ultimately aims to be deleted and
replaced with a netstack-based path.

This commit is part of a series to implement magicDNS using netstack.

Signed-off-by: Tom DNetto <tom@tailscale.com>
This commit is contained in:
Tom DNetto
2022-04-14 13:27:59 -07:00
committed by Tom
parent a54671529b
commit 5b85f848dd
4 changed files with 158 additions and 249 deletions
+2 -79
View File
@@ -27,7 +27,6 @@ import (
"tailscale.com/net/tsdial"
"tailscale.com/tstest"
"tailscale.com/types/dnstype"
"tailscale.com/types/ipproto"
"tailscale.com/util/dnsname"
"tailscale.com/wgengine/monitor"
)
@@ -234,11 +233,7 @@ func unpackResponse(payload []byte) (dnsResponse, error) {
}
func syncRespond(r *Resolver, query []byte) ([]byte, error) {
if err := r.enqueueRequest(query, ipproto.UDP, netaddr.IPPort{}, magicDNSv4Port); err != nil {
return nil, fmt.Errorf("enqueueRequest: %w", err)
}
payload, _, err := r.nextResponse()
return payload, err
return r.Query(context.Background(), query, netaddr.IPPort{})
}
func mustIP(str string) netaddr.IP {
@@ -708,78 +703,6 @@ func TestDelegateSplitRoute(t *testing.T) {
}
}
func TestDelegateCollision(t *testing.T) {
server := serveDNS(t, "127.0.0.1:0",
"test.site.", resolveToIP(testipv4, testipv6, "dns.test.site."))
defer server.Shutdown()
r := newResolver(t)
defer r.Close()
cfg := dnsCfg
cfg.Routes = map[dnsname.FQDN][]dnstype.Resolver{
".": {{Addr: server.PacketConn.LocalAddr().String()}},
}
r.SetConfig(cfg)
packets := []struct {
qname dnsname.FQDN
qtype dns.Type
addr netaddr.IPPort
}{
{"test.site.", dns.TypeA, netaddr.IPPortFrom(netaddr.IPv4(1, 1, 1, 1), 1001)},
{"test.site.", dns.TypeAAAA, netaddr.IPPortFrom(netaddr.IPv4(1, 1, 1, 1), 1002)},
}
// packets will have the same dns txid.
for _, p := range packets {
payload := dnspacket(p.qname, p.qtype, noEdns)
err := r.enqueueRequest(payload, ipproto.UDP, p.addr, magicDNSv4Port)
if err != nil {
t.Error(err)
}
}
// Despite the txid collision, the answer(s) should still match the query.
resp, addr, err := r.nextResponse()
if err != nil {
t.Error(err)
}
var p dns.Parser
_, err = p.Start(resp)
if err != nil {
t.Error(err)
}
err = p.SkipAllQuestions()
if err != nil {
t.Error(err)
}
ans, err := p.AllAnswers()
if err != nil {
t.Error(err)
}
if len(ans) == 0 {
t.Fatal("no answers")
}
var wantType dns.Type
switch ans[0].Body.(type) {
case *dns.AResource:
wantType = dns.TypeA
case *dns.AAAAResource:
wantType = dns.TypeAAAA
default:
t.Errorf("unexpected answer type: %T", ans[0].Body)
}
for _, p := range packets {
if p.qtype == wantType && p.addr != addr {
t.Errorf("addr = %v; want %v", addr, p.addr)
}
}
}
var allResponse = []byte{
0x00, 0x00, // transaction id: 0
0x84, 0x00, // flags: response, authoritative, no error
@@ -1076,7 +999,7 @@ func TestForwardLinkSelection(t *testing.T) {
// routes differently.
specialIP := netaddr.IPv4(1, 2, 3, 4)
fwd := newForwarder(t.Logf, nil, nil, linkSelFunc(func(ip netaddr.IP) string {
fwd := newForwarder(t.Logf, nil, linkSelFunc(func(ip netaddr.IP) string {
if ip == netaddr.IPv4(1, 2, 3, 4) {
return "special"
}