tailcfg, ipn/ipnlocal, net/dns: forward exit node DNS on Unix to system DNS

Updates #1713

Change-Id: I4c073fec0992d9e01a9a4ce97087d5af0efdc68d
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2021-11-29 14:18:09 -08:00
committed by Brad Fitzpatrick
parent d9c21936c3
commit 135580a5a8
7 changed files with 251 additions and 57 deletions

View File

@@ -344,3 +344,48 @@ func TestDNSConfigForNetmap(t *testing.T) {
})
}
}
func TestAllowExitNodeDNSProxyToServeName(t *testing.T) {
b := &LocalBackend{}
if b.allowExitNodeDNSProxyToServeName("google.com") {
t.Fatal("unexpected true on backend with nil NetMap")
}
b.netMap = &netmap.NetworkMap{
DNS: tailcfg.DNSConfig{
ExitNodeFilteredSet: []string{
".ts.net",
"some.exact.bad",
},
},
}
tests := []struct {
name string
want bool
}{
// Allow by default:
{"google.com", true},
{"GOOGLE.com", true},
// Rejected by suffix:
{"foo.TS.NET", false},
{"foo.ts.net", false},
// Suffix doesn't match
{"ts.net", true},
// Rejected by exact match:
{"some.exact.bad", false},
{"SOME.EXACT.BAD", false},
// But a prefix is okay.
{"prefix-okay.some.exact.bad", true},
}
for _, tt := range tests {
got := b.allowExitNodeDNSProxyToServeName(tt.name)
if got != tt.want {
t.Errorf("for %q = %v; want %v", tt.name, got, tt.want)
}
}
}

View File

@@ -3053,3 +3053,34 @@ func (b *LocalBackend) OfferingExitNode() bool {
}
return def4 && def6
}
// allowExitNodeDNSProxyToServeName reports whether the Exit Node DNS
// proxy is allowed to serve responses for the provided DNS name.
func (b *LocalBackend) allowExitNodeDNSProxyToServeName(name string) bool {
b.mu.Lock()
defer b.mu.Unlock()
nm := b.netMap
if nm == nil {
return false
}
name = strings.ToLower(name)
for _, bad := range nm.DNS.ExitNodeFilteredSet {
if bad == "" {
// Invalid, ignore.
continue
}
if bad[0] == '.' {
// Entries beginning with a dot are suffix matches.
if dnsname.HasSuffix(name, bad) {
return false
}
continue
}
// Otherwise entries are exact matches. They're
// guaranteed to be lowercase already.
if name == bad {
return false
}
}
return true
}

View File

@@ -832,7 +832,7 @@ func (h *peerAPIHandler) handleDNSQuery(w http.ResponseWriter, r *http.Request)
ctx, cancel := context.WithTimeout(r.Context(), arbitraryTimeout)
defer cancel()
res, err := h.ps.resolver.HandleExitNodeDNSQuery(ctx, q, h.remoteAddr)
res, err := h.ps.resolver.HandleExitNodeDNSQuery(ctx, q, h.remoteAddr, h.ps.b.allowExitNodeDNSProxyToServeName)
if err != nil {
h.logf("handleDNS fwd error: %v", err)
if err := ctx.Err(); err != nil {
@@ -918,14 +918,19 @@ func writePrettyDNSReply(w io.Writer, res []byte) (err error) {
j, _ := json.Marshal(struct {
Error string
}{err.Error()})
j = append(j, '\n')
w.Write(j)
return
}
}()
var p dnsmessage.Parser
if _, err := p.Start(res); err != nil {
hdr, err := p.Start(res)
if err != nil {
return err
}
if hdr.RCode != dnsmessage.RCodeSuccess {
return fmt.Errorf("DNS RCode = %v", hdr.RCode)
}
if err := p.SkipAllQuestions(); err != nil {
return err
}