mirror of
https://github.com/tailscale/tailscale.git
synced 2025-04-16 03:31:39 +00:00
ipn/ipnlocal, net/dns/resolver: use exit node's DoH proxy when available
Updates #1713 Change-Id: I3695a40ec12d2b4e6dac41cf4559daca6dddd68e Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
16abd7e07c
commit
3ae6f898cf
@ -1974,12 +1974,32 @@ func dnsConfigForNetmap(nm *netmap.NetworkMap, prefs *ipn.Prefs, logf logger.Log
|
|||||||
return dcfg
|
return dcfg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, dom := range nm.DNS.Domains {
|
||||||
|
fqdn, err := dnsname.ToFQDN(dom)
|
||||||
|
if err != nil {
|
||||||
|
logf("[unexpected] non-FQDN search domain %q", dom)
|
||||||
|
}
|
||||||
|
dcfg.SearchDomains = append(dcfg.SearchDomains, fqdn)
|
||||||
|
}
|
||||||
|
if nm.DNS.Proxied { // actually means "enable MagicDNS"
|
||||||
|
for _, dom := range magicDNSRootDomains(nm) {
|
||||||
|
dcfg.Routes[dom] = nil // resolve internally with dcfg.Hosts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
addDefault := func(resolvers []dnstype.Resolver) {
|
addDefault := func(resolvers []dnstype.Resolver) {
|
||||||
for _, r := range resolvers {
|
for _, r := range resolvers {
|
||||||
dcfg.DefaultResolvers = append(dcfg.DefaultResolvers, normalizeResolver(r))
|
dcfg.DefaultResolvers = append(dcfg.DefaultResolvers, normalizeResolver(r))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we're using an exit node and that exit node is new enough (1.19.x+)
|
||||||
|
// to run a DoH DNS proxy, then send all our DNS traffic through it.
|
||||||
|
if dohURL, ok := exitNodeCanProxyDNS(nm, prefs.ExitNodeID); ok {
|
||||||
|
addDefault([]dnstype.Resolver{{Addr: dohURL}})
|
||||||
|
return dcfg
|
||||||
|
}
|
||||||
|
|
||||||
addDefault(nm.DNS.Resolvers)
|
addDefault(nm.DNS.Resolvers)
|
||||||
for suffix, resolvers := range nm.DNS.Routes {
|
for suffix, resolvers := range nm.DNS.Routes {
|
||||||
fqdn, err := dnsname.ToFQDN(suffix)
|
fqdn, err := dnsname.ToFQDN(suffix)
|
||||||
@ -2001,18 +2021,6 @@ func dnsConfigForNetmap(nm *netmap.NetworkMap, prefs *ipn.Prefs, logf logger.Log
|
|||||||
dcfg.Routes[fqdn] = append(dcfg.Routes[fqdn], normalizeResolver(r))
|
dcfg.Routes[fqdn] = append(dcfg.Routes[fqdn], normalizeResolver(r))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, dom := range nm.DNS.Domains {
|
|
||||||
fqdn, err := dnsname.ToFQDN(dom)
|
|
||||||
if err != nil {
|
|
||||||
logf("[unexpected] non-FQDN search domain %q", dom)
|
|
||||||
}
|
|
||||||
dcfg.SearchDomains = append(dcfg.SearchDomains, fqdn)
|
|
||||||
}
|
|
||||||
if nm.DNS.Proxied { // actually means "enable MagicDNS"
|
|
||||||
for _, dom := range magicDNSRootDomains(nm) {
|
|
||||||
dcfg.Routes[dom] = nil // resolve internally with dcfg.Hosts
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set FallbackResolvers as the default resolvers in the
|
// Set FallbackResolvers as the default resolvers in the
|
||||||
// scenarios that can't handle a purely split-DNS config. See
|
// scenarios that can't handle a purely split-DNS config. See
|
||||||
@ -3098,3 +3106,24 @@ func (b *LocalBackend) allowExitNodeDNSProxyToServeName(name string) bool {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// exitNodeCanProxyDNS reports the DoH base URL ("http://foo/dns-query") without query parameters
|
||||||
|
// to exitNodeID's DoH service, if available.
|
||||||
|
//
|
||||||
|
// If exitNodeID is the zero valid, it returns "", false.
|
||||||
|
func exitNodeCanProxyDNS(nm *netmap.NetworkMap, exitNodeID tailcfg.StableNodeID) (dohURL string, ok bool) {
|
||||||
|
if exitNodeID.IsZero() {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
for _, p := range nm.Peers {
|
||||||
|
if p.StableID != exitNodeID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, s := range p.Hostinfo.Services {
|
||||||
|
if s.Proto == tailcfg.PeerAPIDNS && s.Port >= 1 {
|
||||||
|
return peerAPIBase(nm, p) + "/dns-query", true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
@ -423,8 +423,10 @@ func (f *forwarder) sendDoH(ctx context.Context, urlBase string, c *http.Client,
|
|||||||
// send expects the reply to have the same txid as txidOut.
|
// send expects the reply to have the same txid as txidOut.
|
||||||
func (f *forwarder) send(ctx context.Context, fq *forwardQuery, rr resolverAndDelay) ([]byte, error) {
|
func (f *forwarder) send(ctx context.Context, fq *forwardQuery, rr resolverAndDelay) ([]byte, error) {
|
||||||
if strings.HasPrefix(rr.name.Addr, "http://") {
|
if strings.HasPrefix(rr.name.Addr, "http://") {
|
||||||
metricDNSFwdErrorType.Add(1)
|
// TODO(bradfitz): this only work for TUN mode right now; plumb a universal dialer
|
||||||
return nil, fmt.Errorf("http:// resolvers not supported yet")
|
// that can handle the dozen special cases for modes/platforms/routes.
|
||||||
|
TODOHTTPClient := http.DefaultClient
|
||||||
|
return f.sendDoH(ctx, rr.name.Addr, TODOHTTPClient, fq.packet)
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(rr.name.Addr, "https://") {
|
if strings.HasPrefix(rr.name.Addr, "https://") {
|
||||||
metricDNSFwdErrorType.Add(1)
|
metricDNSFwdErrorType.Add(1)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user