github.com/outbrain/consul@v1.4.5/agent/dns.go (about)

     1  package agent
     2  
     3  import (
     4  	"encoding/hex"
     5  	"fmt"
     6  	"log"
     7  	"net"
     8  	"strings"
     9  	"sync/atomic"
    10  	"time"
    11  
    12  	"regexp"
    13  
    14  	metrics "github.com/armon/go-metrics"
    15  	radix "github.com/armon/go-radix"
    16  	"github.com/coredns/coredns/plugin/pkg/dnsutil"
    17  	cachetype "github.com/hashicorp/consul/agent/cache-types"
    18  	"github.com/hashicorp/consul/agent/config"
    19  	"github.com/hashicorp/consul/agent/consul"
    20  	"github.com/hashicorp/consul/agent/structs"
    21  	"github.com/hashicorp/consul/api"
    22  	"github.com/hashicorp/consul/lib"
    23  	"github.com/miekg/dns"
    24  )
    25  
    26  const (
    27  	// UDP can fit ~25 A records in a 512B response, and ~14 AAAA
    28  	// records.  Limit further to prevent unintentional configuration
    29  	// abuse that would have a negative effect on application response
    30  	// times.
    31  	maxUDPAnswerLimit        = 8
    32  	maxRecurseRecords        = 5
    33  	maxRecursionLevelDefault = 3
    34  
    35  	// Increment a counter when requests staler than this are served
    36  	staleCounterThreshold = 5 * time.Second
    37  
    38  	defaultMaxUDPSize = 512
    39  
    40  	MaxDNSLabelLength = 63
    41  )
    42  
    43  var InvalidDnsRe = regexp.MustCompile(`[^A-Za-z0-9\\-]+`)
    44  
    45  type dnsSOAConfig struct {
    46  	Refresh uint32 // 3600 by default
    47  	Retry   uint32 // 600
    48  	Expire  uint32 // 86400
    49  	Minttl  uint32 // 0,
    50  }
    51  
    52  type dnsConfig struct {
    53  	AllowStale      bool
    54  	Datacenter      string
    55  	EnableTruncate  bool
    56  	MaxStale        time.Duration
    57  	UseCache        bool
    58  	CacheMaxAge     time.Duration
    59  	NodeName        string
    60  	NodeTTL         time.Duration
    61  	OnlyPassing     bool
    62  	RecursorTimeout time.Duration
    63  	SegmentName     string
    64  	ServiceTTL      map[string]time.Duration
    65  	UDPAnswerLimit  int
    66  	ARecordLimit    int
    67  	NodeMetaTXT     bool
    68  	dnsSOAConfig    dnsSOAConfig
    69  }
    70  
    71  // DNSServer is used to wrap an Agent and expose various
    72  // service discovery endpoints using a DNS interface.
    73  type DNSServer struct {
    74  	*dns.Server
    75  	agent     *Agent
    76  	config    *dnsConfig
    77  	domain    string
    78  	recursors []string
    79  	logger    *log.Logger
    80  	// Those are handling prefix lookups
    81  	ttlRadix  *radix.Tree
    82  	ttlStrict map[string]time.Duration
    83  
    84  	// disableCompression is the config.DisableCompression flag that can
    85  	// be safely changed at runtime. It always contains a bool and is
    86  	// initialized with the value from config.DisableCompression.
    87  	disableCompression atomic.Value
    88  }
    89  
    90  func NewDNSServer(a *Agent) (*DNSServer, error) {
    91  	var recursors []string
    92  	for _, r := range a.config.DNSRecursors {
    93  		ra, err := recursorAddr(r)
    94  		if err != nil {
    95  			return nil, fmt.Errorf("Invalid recursor address: %v", err)
    96  		}
    97  		recursors = append(recursors, ra)
    98  	}
    99  
   100  	// Make sure domain is FQDN, make it case insensitive for ServeMux
   101  	domain := dns.Fqdn(strings.ToLower(a.config.DNSDomain))
   102  
   103  	dnscfg := GetDNSConfig(a.config)
   104  	srv := &DNSServer{
   105  		agent:     a,
   106  		config:    dnscfg,
   107  		domain:    domain,
   108  		logger:    a.logger,
   109  		recursors: recursors,
   110  		ttlRadix:  radix.New(),
   111  		ttlStrict: make(map[string]time.Duration),
   112  	}
   113  	if dnscfg.ServiceTTL != nil {
   114  		for key, ttl := range dnscfg.ServiceTTL {
   115  			// All suffix with '*' are put in radix
   116  			// This include '*' that will match anything
   117  			if strings.HasSuffix(key, "*") {
   118  				srv.ttlRadix.Insert(key[:len(key)-1], ttl)
   119  			} else {
   120  				srv.ttlStrict[key] = ttl
   121  			}
   122  		}
   123  	}
   124  
   125  	srv.disableCompression.Store(a.config.DNSDisableCompression)
   126  
   127  	return srv, nil
   128  }
   129  
   130  // GetDNSConfig takes global config and creates the config used by DNS server
   131  func GetDNSConfig(conf *config.RuntimeConfig) *dnsConfig {
   132  	return &dnsConfig{
   133  		AllowStale:      conf.DNSAllowStale,
   134  		ARecordLimit:    conf.DNSARecordLimit,
   135  		Datacenter:      conf.Datacenter,
   136  		EnableTruncate:  conf.DNSEnableTruncate,
   137  		MaxStale:        conf.DNSMaxStale,
   138  		NodeName:        conf.NodeName,
   139  		NodeTTL:         conf.DNSNodeTTL,
   140  		OnlyPassing:     conf.DNSOnlyPassing,
   141  		RecursorTimeout: conf.DNSRecursorTimeout,
   142  		SegmentName:     conf.SegmentName,
   143  		ServiceTTL:      conf.DNSServiceTTL,
   144  		UDPAnswerLimit:  conf.DNSUDPAnswerLimit,
   145  		NodeMetaTXT:     conf.DNSNodeMetaTXT,
   146  		UseCache:        conf.DNSUseCache,
   147  		CacheMaxAge:     conf.DNSCacheMaxAge,
   148  		dnsSOAConfig: dnsSOAConfig{
   149  			Expire:  conf.DNSSOA.Expire,
   150  			Minttl:  conf.DNSSOA.Minttl,
   151  			Refresh: conf.DNSSOA.Refresh,
   152  			Retry:   conf.DNSSOA.Retry,
   153  		},
   154  	}
   155  }
   156  
   157  // GetTTLForService Find the TTL for a given service.
   158  // return ttl, true if found, 0, false otherwise
   159  func (d *DNSServer) GetTTLForService(service string) (time.Duration, bool) {
   160  	if d.config.ServiceTTL != nil {
   161  		ttl, ok := d.ttlStrict[service]
   162  		if ok {
   163  			return ttl, true
   164  		}
   165  		_, ttlRaw, ok := d.ttlRadix.LongestPrefix(service)
   166  		if ok {
   167  			return ttlRaw.(time.Duration), true
   168  		}
   169  	}
   170  	return time.Duration(0), false
   171  }
   172  
   173  func (d *DNSServer) ListenAndServe(network, addr string, notif func()) error {
   174  	mux := dns.NewServeMux()
   175  	mux.HandleFunc("arpa.", d.handlePtr)
   176  	mux.HandleFunc(d.domain, d.handleQuery)
   177  	if len(d.recursors) > 0 {
   178  		mux.HandleFunc(".", d.handleRecurse)
   179  	}
   180  
   181  	d.Server = &dns.Server{
   182  		Addr:              addr,
   183  		Net:               network,
   184  		Handler:           mux,
   185  		NotifyStartedFunc: notif,
   186  	}
   187  	if network == "udp" {
   188  		d.UDPSize = 65535
   189  	}
   190  	return d.Server.ListenAndServe()
   191  }
   192  
   193  // setEDNS is used to set the responses EDNS size headers and
   194  // possibly the ECS headers as well if they were present in the
   195  // original request
   196  func setEDNS(request *dns.Msg, response *dns.Msg, ecsGlobal bool) {
   197  	// Enable EDNS if enabled
   198  	if edns := request.IsEdns0(); edns != nil {
   199  		// cannot just use the SetEdns0 function as we need to embed
   200  		// the ECS option as well
   201  		ednsResp := new(dns.OPT)
   202  		ednsResp.Hdr.Name = "."
   203  		ednsResp.Hdr.Rrtype = dns.TypeOPT
   204  		ednsResp.SetUDPSize(edns.UDPSize())
   205  
   206  		// Setup the ECS option if present
   207  		if subnet := ednsSubnetForRequest(request); subnet != nil {
   208  			subOp := new(dns.EDNS0_SUBNET)
   209  			subOp.Code = dns.EDNS0SUBNET
   210  			subOp.Family = subnet.Family
   211  			subOp.Address = subnet.Address
   212  			subOp.SourceNetmask = subnet.SourceNetmask
   213  			if c := response.Rcode; ecsGlobal || c == dns.RcodeNameError || c == dns.RcodeServerFailure || c == dns.RcodeRefused || c == dns.RcodeNotImplemented {
   214  				// reply is globally valid and should be cached accordingly
   215  				subOp.SourceScope = 0
   216  			} else {
   217  				// reply is only valid for the subnet it was queried with
   218  				subOp.SourceScope = subnet.SourceNetmask
   219  			}
   220  			ednsResp.Option = append(ednsResp.Option, subOp)
   221  		}
   222  
   223  		response.Extra = append(response.Extra, ednsResp)
   224  	}
   225  }
   226  
   227  // recursorAddr is used to add a port to the recursor if omitted.
   228  func recursorAddr(recursor string) (string, error) {
   229  	// Add the port if none
   230  START:
   231  	_, _, err := net.SplitHostPort(recursor)
   232  	if ae, ok := err.(*net.AddrError); ok && ae.Err == "missing port in address" {
   233  		recursor = fmt.Sprintf("%s:%d", recursor, 53)
   234  		goto START
   235  	}
   236  	if err != nil {
   237  		return "", err
   238  	}
   239  
   240  	// Get the address
   241  	addr, err := net.ResolveTCPAddr("tcp", recursor)
   242  	if err != nil {
   243  		return "", err
   244  	}
   245  
   246  	// Return string
   247  	return addr.String(), nil
   248  }
   249  
   250  // handlePtr is used to handle "reverse" DNS queries
   251  func (d *DNSServer) handlePtr(resp dns.ResponseWriter, req *dns.Msg) {
   252  	q := req.Question[0]
   253  	defer func(s time.Time) {
   254  		metrics.MeasureSinceWithLabels([]string{"dns", "ptr_query"}, s,
   255  			[]metrics.Label{{Name: "node", Value: d.agent.config.NodeName}})
   256  		d.logger.Printf("[DEBUG] dns: request for %v (%v) from client %s (%s)",
   257  			q, time.Since(s), resp.RemoteAddr().String(),
   258  			resp.RemoteAddr().Network())
   259  	}(time.Now())
   260  
   261  	// Setup the message response
   262  	m := new(dns.Msg)
   263  	m.SetReply(req)
   264  	m.Compress = !d.disableCompression.Load().(bool)
   265  	m.Authoritative = true
   266  	m.RecursionAvailable = (len(d.recursors) > 0)
   267  
   268  	// Only add the SOA if requested
   269  	if req.Question[0].Qtype == dns.TypeSOA {
   270  		d.addSOA(m)
   271  	}
   272  
   273  	datacenter := d.agent.config.Datacenter
   274  
   275  	// Get the QName without the domain suffix
   276  	qName := strings.ToLower(dns.Fqdn(req.Question[0].Name))
   277  
   278  	args := structs.DCSpecificRequest{
   279  		Datacenter: datacenter,
   280  		QueryOptions: structs.QueryOptions{
   281  			Token:      d.agent.tokens.UserToken(),
   282  			AllowStale: d.config.AllowStale,
   283  		},
   284  	}
   285  	var out structs.IndexedNodes
   286  
   287  	// TODO: Replace ListNodes with an internal RPC that can do the filter
   288  	// server side to avoid transferring the entire node list.
   289  	if err := d.agent.RPC("Catalog.ListNodes", &args, &out); err == nil {
   290  		for _, n := range out.Nodes {
   291  			arpa, _ := dns.ReverseAddr(n.Address)
   292  			if arpa == qName {
   293  				ptr := &dns.PTR{
   294  					Hdr: dns.RR_Header{Name: q.Name, Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: 0},
   295  					Ptr: fmt.Sprintf("%s.node.%s.%s", n.Node, datacenter, d.domain),
   296  				}
   297  				m.Answer = append(m.Answer, ptr)
   298  				break
   299  			}
   300  		}
   301  	}
   302  
   303  	// only look into the services if we didn't find a node
   304  	if len(m.Answer) == 0 {
   305  		// lookup the service address
   306  		serviceAddress := dnsutil.ExtractAddressFromReverse(qName)
   307  		sargs := structs.ServiceSpecificRequest{
   308  			Datacenter: datacenter,
   309  			QueryOptions: structs.QueryOptions{
   310  				Token:      d.agent.tokens.UserToken(),
   311  				AllowStale: d.config.AllowStale,
   312  			},
   313  			ServiceAddress: serviceAddress,
   314  		}
   315  
   316  		var sout structs.IndexedServiceNodes
   317  		if err := d.agent.RPC("Catalog.ServiceNodes", &sargs, &sout); err == nil {
   318  			for _, n := range sout.ServiceNodes {
   319  				if n.ServiceAddress == serviceAddress {
   320  					ptr := &dns.PTR{
   321  						Hdr: dns.RR_Header{Name: q.Name, Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: 0},
   322  						Ptr: fmt.Sprintf("%s.service.%s", n.ServiceName, d.domain),
   323  					}
   324  					m.Answer = append(m.Answer, ptr)
   325  					break
   326  				}
   327  			}
   328  		}
   329  	}
   330  
   331  	// nothing found locally, recurse
   332  	if len(m.Answer) == 0 {
   333  		d.handleRecurse(resp, req)
   334  		return
   335  	}
   336  
   337  	// ptr record responses are globally valid
   338  	setEDNS(req, m, true)
   339  
   340  	// Write out the complete response
   341  	if err := resp.WriteMsg(m); err != nil {
   342  		d.logger.Printf("[WARN] dns: failed to respond: %v", err)
   343  	}
   344  }
   345  
   346  // handleQuery is used to handle DNS queries in the configured domain
   347  func (d *DNSServer) handleQuery(resp dns.ResponseWriter, req *dns.Msg) {
   348  	q := req.Question[0]
   349  	defer func(s time.Time) {
   350  		metrics.MeasureSinceWithLabels([]string{"dns", "domain_query"}, s,
   351  			[]metrics.Label{{Name: "node", Value: d.agent.config.NodeName}})
   352  		d.logger.Printf("[DEBUG] dns: request for name %v type %v class %v (took %v) from client %s (%s)",
   353  			q.Name, dns.Type(q.Qtype), dns.Class(q.Qclass), time.Since(s), resp.RemoteAddr().String(),
   354  			resp.RemoteAddr().Network())
   355  	}(time.Now())
   356  
   357  	// Switch to TCP if the client is
   358  	network := "udp"
   359  	if _, ok := resp.RemoteAddr().(*net.TCPAddr); ok {
   360  		network = "tcp"
   361  	}
   362  
   363  	// Setup the message response
   364  	m := new(dns.Msg)
   365  	m.SetReply(req)
   366  	m.Compress = !d.disableCompression.Load().(bool)
   367  	m.Authoritative = true
   368  	m.RecursionAvailable = (len(d.recursors) > 0)
   369  
   370  	ecsGlobal := true
   371  
   372  	switch req.Question[0].Qtype {
   373  	case dns.TypeSOA:
   374  		ns, glue := d.nameservers(req.IsEdns0() != nil, maxRecursionLevelDefault)
   375  		m.Answer = append(m.Answer, d.soa())
   376  		m.Ns = append(m.Ns, ns...)
   377  		m.Extra = append(m.Extra, glue...)
   378  		m.SetRcode(req, dns.RcodeSuccess)
   379  
   380  	case dns.TypeNS:
   381  		ns, glue := d.nameservers(req.IsEdns0() != nil, maxRecursionLevelDefault)
   382  		m.Answer = ns
   383  		m.Extra = glue
   384  		m.SetRcode(req, dns.RcodeSuccess)
   385  
   386  	case dns.TypeAXFR:
   387  		m.SetRcode(req, dns.RcodeNotImplemented)
   388  
   389  	default:
   390  		ecsGlobal = d.dispatch(network, resp.RemoteAddr(), req, m)
   391  	}
   392  
   393  	setEDNS(req, m, ecsGlobal)
   394  
   395  	// Write out the complete response
   396  	if err := resp.WriteMsg(m); err != nil {
   397  		d.logger.Printf("[WARN] dns: failed to respond: %v", err)
   398  	}
   399  }
   400  
   401  func (d *DNSServer) soa() *dns.SOA {
   402  	return &dns.SOA{
   403  		Hdr: dns.RR_Header{
   404  			Name:   d.domain,
   405  			Rrtype: dns.TypeSOA,
   406  			Class:  dns.ClassINET,
   407  			// Has to be consistent with MinTTL to avoid invalidation
   408  			Ttl: d.config.dnsSOAConfig.Minttl,
   409  		},
   410  		Ns:      "ns." + d.domain,
   411  		Serial:  uint32(time.Now().Unix()),
   412  		Mbox:    "hostmaster." + d.domain,
   413  		Refresh: d.config.dnsSOAConfig.Refresh,
   414  		Retry:   d.config.dnsSOAConfig.Retry,
   415  		Expire:  d.config.dnsSOAConfig.Expire,
   416  		Minttl:  d.config.dnsSOAConfig.Minttl,
   417  	}
   418  }
   419  
   420  // addSOA is used to add an SOA record to a message for the given domain
   421  func (d *DNSServer) addSOA(msg *dns.Msg) {
   422  	msg.Ns = append(msg.Ns, d.soa())
   423  }
   424  
   425  // nameservers returns the names and ip addresses of up to three random servers
   426  // in the current cluster which serve as authoritative name servers for zone.
   427  func (d *DNSServer) nameservers(edns bool, maxRecursionLevel int) (ns []dns.RR, extra []dns.RR) {
   428  	out, err := d.lookupServiceNodes(d.agent.config.Datacenter, structs.ConsulServiceName, "", false, maxRecursionLevel)
   429  	if err != nil {
   430  		d.logger.Printf("[WARN] dns: Unable to get list of servers: %s", err)
   431  		return nil, nil
   432  	}
   433  
   434  	if len(out.Nodes) == 0 {
   435  		d.logger.Printf("[WARN] dns: no servers found")
   436  		return
   437  	}
   438  
   439  	// shuffle the nodes to randomize the output
   440  	out.Nodes.Shuffle()
   441  
   442  	for _, o := range out.Nodes {
   443  		name, addr, dc := o.Node.Node, o.Node.Address, o.Node.Datacenter
   444  
   445  		if InvalidDnsRe.MatchString(name) {
   446  			d.logger.Printf("[WARN] dns: Skipping invalid node %q for NS records", name)
   447  			continue
   448  		}
   449  
   450  		fqdn := name + ".node." + dc + "." + d.domain
   451  		fqdn = dns.Fqdn(strings.ToLower(fqdn))
   452  
   453  		// NS record
   454  		nsrr := &dns.NS{
   455  			Hdr: dns.RR_Header{
   456  				Name:   d.domain,
   457  				Rrtype: dns.TypeNS,
   458  				Class:  dns.ClassINET,
   459  				Ttl:    uint32(d.config.NodeTTL / time.Second),
   460  			},
   461  			Ns: fqdn,
   462  		}
   463  		ns = append(ns, nsrr)
   464  
   465  		glue, meta := d.formatNodeRecord(nil, addr, fqdn, dns.TypeANY, d.config.NodeTTL, edns, maxRecursionLevel, d.config.NodeMetaTXT)
   466  		extra = append(extra, glue...)
   467  		if meta != nil && d.config.NodeMetaTXT {
   468  			extra = append(extra, meta...)
   469  		}
   470  
   471  		// don't provide more than 3 servers
   472  		if len(ns) >= 3 {
   473  			return
   474  		}
   475  	}
   476  
   477  	return
   478  }
   479  
   480  // dispatch is used to parse a request and invoke the correct handler
   481  func (d *DNSServer) dispatch(network string, remoteAddr net.Addr, req, resp *dns.Msg) (ecsGlobal bool) {
   482  	return d.doDispatch(network, remoteAddr, req, resp, maxRecursionLevelDefault)
   483  }
   484  
   485  // doDispatch is used to parse a request and invoke the correct handler.
   486  // parameter maxRecursionLevel will handle whether recursive call can be performed
   487  func (d *DNSServer) doDispatch(network string, remoteAddr net.Addr, req, resp *dns.Msg, maxRecursionLevel int) (ecsGlobal bool) {
   488  	ecsGlobal = true
   489  	// By default the query is in the default datacenter
   490  	datacenter := d.agent.config.Datacenter
   491  
   492  	// Get the QName without the domain suffix
   493  	qName := strings.ToLower(dns.Fqdn(req.Question[0].Name))
   494  	qName = strings.TrimSuffix(qName, d.domain)
   495  
   496  	// Split into the label parts
   497  	labels := dns.SplitDomainName(qName)
   498  
   499  	// Provide a flag for remembering whether the datacenter name was parsed already.
   500  	var dcParsed bool
   501  
   502  	// The last label is either "node", "service", "query", "_<protocol>", or a datacenter name
   503  PARSE:
   504  	n := len(labels)
   505  	if n == 0 {
   506  		goto INVALID
   507  	}
   508  
   509  	// If this is a SRV query the "service" label is optional, we add it back to use the
   510  	// existing code-path.
   511  	if req.Question[0].Qtype == dns.TypeSRV && strings.HasPrefix(labels[n-1], "_") {
   512  		labels = append(labels, "service")
   513  		n = n + 1
   514  	}
   515  
   516  	switch kind := labels[n-1]; kind {
   517  	case "service":
   518  		if n == 1 {
   519  			goto INVALID
   520  		}
   521  
   522  		// Support RFC 2782 style syntax
   523  		if n == 3 && strings.HasPrefix(labels[n-2], "_") && strings.HasPrefix(labels[n-3], "_") {
   524  
   525  			// Grab the tag since we make nuke it if it's tcp
   526  			tag := labels[n-2][1:]
   527  
   528  			// Treat _name._tcp.service.consul as a default, no need to filter on that tag
   529  			if tag == "tcp" {
   530  				tag = ""
   531  			}
   532  
   533  			// _name._tag.service.consul
   534  			d.serviceLookup(network, datacenter, labels[n-3][1:], tag, false, req, resp, maxRecursionLevel)
   535  
   536  			// Consul 0.3 and prior format for SRV queries
   537  		} else {
   538  
   539  			// Support "." in the label, re-join all the parts
   540  			tag := ""
   541  			if n >= 3 {
   542  				tag = strings.Join(labels[:n-2], ".")
   543  			}
   544  
   545  			// tag[.tag].name.service.consul
   546  			d.serviceLookup(network, datacenter, labels[n-2], tag, false, req, resp, maxRecursionLevel)
   547  		}
   548  
   549  	case "connect":
   550  		if n == 1 {
   551  			goto INVALID
   552  		}
   553  
   554  		// name.connect.consul
   555  		d.serviceLookup(network, datacenter, labels[n-2], "", true, req, resp, maxRecursionLevel)
   556  
   557  	case "node":
   558  		if n == 1 {
   559  			goto INVALID
   560  		}
   561  
   562  		// Allow a "." in the node name, just join all the parts
   563  		node := strings.Join(labels[:n-1], ".")
   564  		d.nodeLookup(network, datacenter, node, req, resp, maxRecursionLevel)
   565  
   566  	case "query":
   567  		if n == 1 {
   568  			goto INVALID
   569  		}
   570  
   571  		// Allow a "." in the query name, just join all the parts.
   572  		query := strings.Join(labels[:n-1], ".")
   573  		ecsGlobal = false
   574  		d.preparedQueryLookup(network, datacenter, query, remoteAddr, req, resp, maxRecursionLevel)
   575  
   576  	case "addr":
   577  		if n != 2 {
   578  			goto INVALID
   579  		}
   580  
   581  		switch len(labels[0]) / 2 {
   582  		// IPv4
   583  		case 4:
   584  			ip, err := hex.DecodeString(labels[0])
   585  			if err != nil {
   586  				goto INVALID
   587  			}
   588  
   589  			resp.Answer = append(resp.Answer, &dns.A{
   590  				Hdr: dns.RR_Header{
   591  					Name:   qName + d.domain,
   592  					Rrtype: dns.TypeA,
   593  					Class:  dns.ClassINET,
   594  					Ttl:    uint32(d.config.NodeTTL / time.Second),
   595  				},
   596  				A: ip,
   597  			})
   598  		// IPv6
   599  		case 16:
   600  			ip, err := hex.DecodeString(labels[0])
   601  			if err != nil {
   602  				goto INVALID
   603  			}
   604  
   605  			resp.Answer = append(resp.Answer, &dns.AAAA{
   606  				Hdr: dns.RR_Header{
   607  					Name:   qName + d.domain,
   608  					Rrtype: dns.TypeAAAA,
   609  					Class:  dns.ClassINET,
   610  					Ttl:    uint32(d.config.NodeTTL / time.Second),
   611  				},
   612  				AAAA: ip,
   613  			})
   614  		}
   615  
   616  	default:
   617  		// https://github.com/hashicorp/consul/issues/3200
   618  		//
   619  		// Since datacenter names cannot contain dots we can only allow one
   620  		// label between the query type and the domain to be the datacenter name.
   621  		// Since the datacenter name is optional and the parser strips off labels at the end until it finds a suitable
   622  		// query type label we return NXDOMAIN when we encounter another label
   623  		// which could be the datacenter name.
   624  		//
   625  		// If '.consul' is the domain then
   626  		//  * foo.service.dc.consul is OK
   627  		//  * foo.service.dc.stuff.consul is not OK
   628  		if dcParsed {
   629  			goto INVALID
   630  		}
   631  		dcParsed = true
   632  
   633  		// Store the DC, and re-parse
   634  		datacenter = labels[n-1]
   635  		labels = labels[:n-1]
   636  		goto PARSE
   637  	}
   638  	return
   639  INVALID:
   640  	d.logger.Printf("[WARN] dns: QName invalid: %s", qName)
   641  	d.addSOA(resp)
   642  	resp.SetRcode(req, dns.RcodeNameError)
   643  	return
   644  }
   645  
   646  // nodeLookup is used to handle a node query
   647  func (d *DNSServer) nodeLookup(network, datacenter, node string, req, resp *dns.Msg, maxRecursionLevel int) {
   648  	// Only handle ANY, A, AAAA, and TXT type requests
   649  	qType := req.Question[0].Qtype
   650  	if qType != dns.TypeANY && qType != dns.TypeA && qType != dns.TypeAAAA && qType != dns.TypeTXT {
   651  		return
   652  	}
   653  
   654  	// Make an RPC request
   655  	args := &structs.NodeSpecificRequest{
   656  		Datacenter: datacenter,
   657  		Node:       node,
   658  		QueryOptions: structs.QueryOptions{
   659  			Token:      d.agent.tokens.UserToken(),
   660  			AllowStale: d.config.AllowStale,
   661  		},
   662  	}
   663  	out, err := d.lookupNode(args)
   664  	if err != nil {
   665  		d.logger.Printf("[ERR] dns: rpc error: %v", err)
   666  		resp.SetRcode(req, dns.RcodeServerFailure)
   667  		return
   668  	}
   669  
   670  	// If we have no address, return not found!
   671  	if out.NodeServices == nil {
   672  		d.addSOA(resp)
   673  		resp.SetRcode(req, dns.RcodeNameError)
   674  		return
   675  	}
   676  
   677  	generateMeta := false
   678  	metaInAnswer := false
   679  	if qType == dns.TypeANY || qType == dns.TypeTXT {
   680  		generateMeta = true
   681  		metaInAnswer = true
   682  	} else if d.config.NodeMetaTXT {
   683  		generateMeta = true
   684  	}
   685  
   686  	// Add the node record
   687  	n := out.NodeServices.Node
   688  	edns := req.IsEdns0() != nil
   689  	addr := d.agent.TranslateAddress(datacenter, n.Address, n.TaggedAddresses)
   690  	records, meta := d.formatNodeRecord(out.NodeServices.Node, addr, req.Question[0].Name, qType, d.config.NodeTTL, edns, maxRecursionLevel, generateMeta)
   691  	if records != nil {
   692  		resp.Answer = append(resp.Answer, records...)
   693  	}
   694  	if meta != nil && metaInAnswer && generateMeta {
   695  		resp.Answer = append(resp.Answer, meta...)
   696  	} else if meta != nil && generateMeta {
   697  		resp.Extra = append(resp.Extra, meta...)
   698  	}
   699  }
   700  
   701  func (d *DNSServer) lookupNode(args *structs.NodeSpecificRequest) (*structs.IndexedNodeServices, error) {
   702  	var out structs.IndexedNodeServices
   703  
   704  	useCache := d.config.UseCache
   705  RPC:
   706  	if useCache {
   707  		raw, _, err := d.agent.cache.Get(cachetype.NodeServicesName, args)
   708  		if err != nil {
   709  			return nil, err
   710  		}
   711  		reply, ok := raw.(*structs.IndexedNodeServices)
   712  		if !ok {
   713  			// This should never happen, but we want to protect against panics
   714  			return nil, fmt.Errorf("internal error: response type not correct")
   715  		}
   716  		out = *reply
   717  	} else {
   718  		if err := d.agent.RPC("Catalog.NodeServices", &args, &out); err != nil {
   719  			return nil, err
   720  		}
   721  	}
   722  
   723  	// Verify that request is not too stale, redo the request
   724  	if args.AllowStale {
   725  		if out.LastContact > d.config.MaxStale {
   726  			args.AllowStale = false
   727  			useCache = false
   728  			d.logger.Printf("[WARN] dns: Query results too stale, re-requesting")
   729  			goto RPC
   730  		} else if out.LastContact > staleCounterThreshold {
   731  			metrics.IncrCounter([]string{"dns", "stale_queries"}, 1)
   732  		}
   733  	}
   734  
   735  	return &out, nil
   736  }
   737  
   738  // encodeKVasRFC1464 encodes a key-value pair according to RFC1464
   739  func encodeKVasRFC1464(key, value string) (txt string) {
   740  	// For details on these replacements c.f. https://www.ietf.org/rfc/rfc1464.txt
   741  	key = strings.Replace(key, "`", "``", -1)
   742  	key = strings.Replace(key, "=", "`=", -1)
   743  
   744  	// Backquote the leading spaces
   745  	leadingSpacesRE := regexp.MustCompile("^ +")
   746  	numLeadingSpaces := len(leadingSpacesRE.FindString(key))
   747  	key = leadingSpacesRE.ReplaceAllString(key, strings.Repeat("` ", numLeadingSpaces))
   748  
   749  	// Backquote the trailing spaces
   750  	trailingSpacesRE := regexp.MustCompile(" +$")
   751  	numTrailingSpaces := len(trailingSpacesRE.FindString(key))
   752  	key = trailingSpacesRE.ReplaceAllString(key, strings.Repeat("` ", numTrailingSpaces))
   753  
   754  	value = strings.Replace(value, "`", "``", -1)
   755  
   756  	return key + "=" + value
   757  }
   758  
   759  // formatNodeRecord takes a Node and returns the RRs associated with that node
   760  //
   761  // The return value is two slices. The first slice is the main answer slice (containing the A, AAAA, CNAME) RRs for the node
   762  // and the second slice contains any TXT RRs created from the node metadata. It is up to the caller to determine where the
   763  // generated RRs should go and if they should be used at all.
   764  func (d *DNSServer) formatNodeRecord(node *structs.Node, addr, qName string, qType uint16, ttl time.Duration, edns bool, maxRecursionLevel int, generateMeta bool) (records, meta []dns.RR) {
   765  	// Parse the IP
   766  	ip := net.ParseIP(addr)
   767  	var ipv4 net.IP
   768  	if ip != nil {
   769  		ipv4 = ip.To4()
   770  	}
   771  
   772  	switch {
   773  	case ipv4 != nil && (qType == dns.TypeANY || qType == dns.TypeA):
   774  		records = append(records, &dns.A{
   775  			Hdr: dns.RR_Header{
   776  				Name:   qName,
   777  				Rrtype: dns.TypeA,
   778  				Class:  dns.ClassINET,
   779  				Ttl:    uint32(ttl / time.Second),
   780  			},
   781  			A: ip,
   782  		})
   783  
   784  	case ip != nil && ipv4 == nil && (qType == dns.TypeANY || qType == dns.TypeAAAA):
   785  		records = append(records, &dns.AAAA{
   786  			Hdr: dns.RR_Header{
   787  				Name:   qName,
   788  				Rrtype: dns.TypeAAAA,
   789  				Class:  dns.ClassINET,
   790  				Ttl:    uint32(ttl / time.Second),
   791  			},
   792  			AAAA: ip,
   793  		})
   794  
   795  	case ip == nil && (qType == dns.TypeANY || qType == dns.TypeCNAME ||
   796  		qType == dns.TypeA || qType == dns.TypeAAAA || qType == dns.TypeTXT):
   797  		// Get the CNAME
   798  		cnRec := &dns.CNAME{
   799  			Hdr: dns.RR_Header{
   800  				Name:   qName,
   801  				Rrtype: dns.TypeCNAME,
   802  				Class:  dns.ClassINET,
   803  				Ttl:    uint32(ttl / time.Second),
   804  			},
   805  			Target: dns.Fqdn(addr),
   806  		}
   807  		records = append(records, cnRec)
   808  
   809  		// Recurse
   810  		more := d.resolveCNAME(cnRec.Target, maxRecursionLevel)
   811  		extra := 0
   812  	MORE_REC:
   813  		for _, rr := range more {
   814  			switch rr.Header().Rrtype {
   815  			case dns.TypeCNAME, dns.TypeA, dns.TypeAAAA, dns.TypeTXT:
   816  				records = append(records, rr)
   817  				extra++
   818  				if extra == maxRecurseRecords && !edns {
   819  					break MORE_REC
   820  				}
   821  			}
   822  		}
   823  	}
   824  
   825  	if node != nil && generateMeta {
   826  		for key, value := range node.Meta {
   827  			txt := value
   828  			if !strings.HasPrefix(strings.ToLower(key), "rfc1035-") {
   829  				txt = encodeKVasRFC1464(key, value)
   830  			}
   831  
   832  			meta = append(meta, &dns.TXT{
   833  				Hdr: dns.RR_Header{
   834  					Name:   qName,
   835  					Rrtype: dns.TypeTXT,
   836  					Class:  dns.ClassINET,
   837  					Ttl:    uint32(ttl / time.Second),
   838  				},
   839  				Txt: []string{txt},
   840  			})
   841  		}
   842  	}
   843  
   844  	return records, meta
   845  }
   846  
   847  // indexRRs populates a map which indexes a given list of RRs by name. NOTE that
   848  // the names are all squashed to lower case so we can perform case-insensitive
   849  // lookups; the RRs are not modified.
   850  func indexRRs(rrs []dns.RR, index map[string]dns.RR) {
   851  	for _, rr := range rrs {
   852  		name := strings.ToLower(rr.Header().Name)
   853  		if _, ok := index[name]; !ok {
   854  			index[name] = rr
   855  		}
   856  	}
   857  }
   858  
   859  // syncExtra takes a DNS response message and sets the extra data to the most
   860  // minimal set needed to cover the answer data. A pre-made index of RRs is given
   861  // so that can be re-used between calls. This assumes that the extra data is
   862  // only used to provide info for SRV records. If that's not the case, then this
   863  // will wipe out any additional data.
   864  func syncExtra(index map[string]dns.RR, resp *dns.Msg) {
   865  	extra := make([]dns.RR, 0, len(resp.Answer))
   866  	resolved := make(map[string]struct{}, len(resp.Answer))
   867  	for _, ansRR := range resp.Answer {
   868  		srv, ok := ansRR.(*dns.SRV)
   869  		if !ok {
   870  			continue
   871  		}
   872  
   873  		// Note that we always use lower case when using the index so
   874  		// that compares are not case-sensitive. We don't alter the actual
   875  		// RRs we add into the extra section, however.
   876  		target := strings.ToLower(srv.Target)
   877  
   878  	RESOLVE:
   879  		if _, ok := resolved[target]; ok {
   880  			continue
   881  		}
   882  		resolved[target] = struct{}{}
   883  
   884  		extraRR, ok := index[target]
   885  		if ok {
   886  			extra = append(extra, extraRR)
   887  			if cname, ok := extraRR.(*dns.CNAME); ok {
   888  				target = strings.ToLower(cname.Target)
   889  				goto RESOLVE
   890  			}
   891  		}
   892  	}
   893  	resp.Extra = extra
   894  }
   895  
   896  // dnsBinaryTruncate find the optimal number of records using a fast binary search and return
   897  // it in order to return a DNS answer lower than maxSize parameter.
   898  func dnsBinaryTruncate(resp *dns.Msg, maxSize int, index map[string]dns.RR, hasExtra bool) int {
   899  	originalAnswser := resp.Answer
   900  	startIndex := 0
   901  	endIndex := len(resp.Answer) + 1
   902  	for endIndex-startIndex > 1 {
   903  		median := startIndex + (endIndex-startIndex)/2
   904  
   905  		resp.Answer = originalAnswser[:median]
   906  		if hasExtra {
   907  			syncExtra(index, resp)
   908  		}
   909  		aLen := resp.Len()
   910  		if aLen <= maxSize {
   911  			if maxSize-aLen < 10 {
   912  				// We are good, increasing will go out of bounds
   913  				return median
   914  			}
   915  			startIndex = median
   916  		} else {
   917  			endIndex = median
   918  		}
   919  	}
   920  	return startIndex
   921  }
   922  
   923  // trimTCPResponse limit the MaximumSize of messages to 64k as it is the limit
   924  // of DNS responses
   925  func (d *DNSServer) trimTCPResponse(req, resp *dns.Msg) (trimmed bool) {
   926  	hasExtra := len(resp.Extra) > 0
   927  	// There is some overhead, 65535 does not work
   928  	maxSize := 65523 // 64k - 12 bytes DNS raw overhead
   929  
   930  	// We avoid some function calls and allocations by only handling the
   931  	// extra data when necessary.
   932  	var index map[string]dns.RR
   933  	originalSize := resp.Len()
   934  	originalNumRecords := len(resp.Answer)
   935  
   936  	// It is not possible to return more than 4k records even with compression
   937  	// Since we are performing binary search it is not a big deal, but it
   938  	// improves a bit performance, even with binary search
   939  	truncateAt := 4096
   940  	if req.Question[0].Qtype == dns.TypeSRV {
   941  		// More than 1024 SRV records do not fit in 64k
   942  		truncateAt = 1024
   943  	}
   944  	if len(resp.Answer) > truncateAt {
   945  		resp.Answer = resp.Answer[:truncateAt]
   946  	}
   947  	if hasExtra {
   948  		index = make(map[string]dns.RR, len(resp.Extra))
   949  		indexRRs(resp.Extra, index)
   950  	}
   951  	truncated := false
   952  
   953  	// This enforces the given limit on 64k, the max limit for DNS messages
   954  	for len(resp.Answer) > 1 && resp.Len() > maxSize {
   955  		truncated = true
   956  		// More than 100 bytes, find with a binary search
   957  		if resp.Len()-maxSize > 100 {
   958  			bestIndex := dnsBinaryTruncate(resp, maxSize, index, hasExtra)
   959  			resp.Answer = resp.Answer[:bestIndex]
   960  		} else {
   961  			resp.Answer = resp.Answer[:len(resp.Answer)-1]
   962  		}
   963  		if hasExtra {
   964  			syncExtra(index, resp)
   965  		}
   966  	}
   967  	if truncated {
   968  		d.logger.Printf("[DEBUG] dns: TCP answer to %v too large truncated recs:=%d/%d, size:=%d/%d",
   969  			req.Question,
   970  			len(resp.Answer), originalNumRecords, resp.Len(), originalSize)
   971  	}
   972  	return truncated
   973  }
   974  
   975  // trimUDPResponse makes sure a UDP response is not longer than allowed by RFC
   976  // 1035. Enforce an arbitrary limit that can be further ratcheted down by
   977  // config, and then make sure the response doesn't exceed 512 bytes. Any extra
   978  // records will be trimmed along with answers.
   979  func trimUDPResponse(req, resp *dns.Msg, udpAnswerLimit int) (trimmed bool) {
   980  	numAnswers := len(resp.Answer)
   981  	hasExtra := len(resp.Extra) > 0
   982  	maxSize := defaultMaxUDPSize
   983  
   984  	// Update to the maximum edns size
   985  	if edns := req.IsEdns0(); edns != nil {
   986  		if size := edns.UDPSize(); size > uint16(maxSize) {
   987  			maxSize = int(size)
   988  		}
   989  	}
   990  
   991  	// We avoid some function calls and allocations by only handling the
   992  	// extra data when necessary.
   993  	var index map[string]dns.RR
   994  	if hasExtra {
   995  		index = make(map[string]dns.RR, len(resp.Extra))
   996  		indexRRs(resp.Extra, index)
   997  	}
   998  
   999  	// This cuts UDP responses to a useful but limited number of responses.
  1000  	maxAnswers := lib.MinInt(maxUDPAnswerLimit, udpAnswerLimit)
  1001  	compress := resp.Compress
  1002  	if maxSize == defaultMaxUDPSize && numAnswers > maxAnswers {
  1003  		// We disable computation of Len ONLY for non-eDNS request (512 bytes)
  1004  		resp.Compress = false
  1005  		resp.Answer = resp.Answer[:maxAnswers]
  1006  		if hasExtra {
  1007  			syncExtra(index, resp)
  1008  		}
  1009  	}
  1010  
  1011  	// This enforces the given limit on the number bytes. The default is 512 as
  1012  	// per the RFC, but EDNS0 allows for the user to specify larger sizes. Note
  1013  	// that we temporarily switch to uncompressed so that we limit to a response
  1014  	// that will not exceed 512 bytes uncompressed, which is more conservative and
  1015  	// will allow our responses to be compliant even if some downstream server
  1016  	// uncompresses them.
  1017  	// Even when size is too big for one single record, try to send it anyway
  1018  	// (useful for 512 bytes messages)
  1019  	for len(resp.Answer) > 1 && resp.Len() > maxSize {
  1020  		// More than 100 bytes, find with a binary search
  1021  		if resp.Len()-maxSize > 100 {
  1022  			bestIndex := dnsBinaryTruncate(resp, maxSize, index, hasExtra)
  1023  			resp.Answer = resp.Answer[:bestIndex]
  1024  		} else {
  1025  			resp.Answer = resp.Answer[:len(resp.Answer)-1]
  1026  		}
  1027  		if hasExtra {
  1028  			syncExtra(index, resp)
  1029  		}
  1030  	}
  1031  	// For 512 non-eDNS responses, while we compute size non-compressed,
  1032  	// we send result compressed
  1033  	resp.Compress = compress
  1034  
  1035  	return len(resp.Answer) < numAnswers
  1036  }
  1037  
  1038  // trimDNSResponse will trim the response for UDP and TCP
  1039  func (d *DNSServer) trimDNSResponse(network string, req, resp *dns.Msg) (trimmed bool) {
  1040  	if network != "tcp" {
  1041  		trimmed = trimUDPResponse(req, resp, d.config.UDPAnswerLimit)
  1042  	} else {
  1043  		trimmed = d.trimTCPResponse(req, resp)
  1044  	}
  1045  	// Flag that there are more records to return in the UDP response
  1046  	if trimmed && d.config.EnableTruncate {
  1047  		resp.Truncated = true
  1048  	}
  1049  	return trimmed
  1050  }
  1051  
  1052  // lookupServiceNodes returns nodes with a given service.
  1053  func (d *DNSServer) lookupServiceNodes(datacenter, service, tag string, connect bool, maxRecursionLevel int) (structs.IndexedCheckServiceNodes, error) {
  1054  	args := structs.ServiceSpecificRequest{
  1055  		Connect:     connect,
  1056  		Datacenter:  datacenter,
  1057  		ServiceName: service,
  1058  		ServiceTags: []string{tag},
  1059  		TagFilter:   tag != "",
  1060  		QueryOptions: structs.QueryOptions{
  1061  			Token:      d.agent.tokens.UserToken(),
  1062  			AllowStale: d.config.AllowStale,
  1063  			MaxAge:     d.config.CacheMaxAge,
  1064  		},
  1065  	}
  1066  
  1067  	var out structs.IndexedCheckServiceNodes
  1068  
  1069  	if d.config.UseCache {
  1070  		raw, m, err := d.agent.cache.Get(cachetype.HealthServicesName, &args)
  1071  		if err != nil {
  1072  			return out, err
  1073  		}
  1074  		reply, ok := raw.(*structs.IndexedCheckServiceNodes)
  1075  		if !ok {
  1076  			// This should never happen, but we want to protect against panics
  1077  			return out, fmt.Errorf("internal error: response type not correct")
  1078  		}
  1079  		d.logger.Printf("[TRACE] dns: cache hit: %v for service %s", m.Hit, service)
  1080  
  1081  		out = *reply
  1082  	} else {
  1083  		if err := d.agent.RPC("Health.ServiceNodes", &args, &out); err != nil {
  1084  			return out, err
  1085  		}
  1086  	}
  1087  
  1088  	if args.AllowStale && out.LastContact > staleCounterThreshold {
  1089  		metrics.IncrCounter([]string{"dns", "stale_queries"}, 1)
  1090  	}
  1091  
  1092  	// redo the request the response was too stale
  1093  	if args.AllowStale && out.LastContact > d.config.MaxStale {
  1094  		args.AllowStale = false
  1095  		d.logger.Printf("[WARN] dns: Query results too stale, re-requesting")
  1096  
  1097  		if err := d.agent.RPC("Health.ServiceNodes", &args, &out); err != nil {
  1098  			return structs.IndexedCheckServiceNodes{}, err
  1099  		}
  1100  	}
  1101  
  1102  	// Filter out any service nodes due to health checks
  1103  	// We copy the slice to avoid modifying the result if it comes from the cache
  1104  	nodes := make(structs.CheckServiceNodes, len(out.Nodes))
  1105  	copy(nodes, out.Nodes)
  1106  	out.Nodes = nodes.Filter(d.config.OnlyPassing)
  1107  	return out, nil
  1108  }
  1109  
  1110  // serviceLookup is used to handle a service query
  1111  func (d *DNSServer) serviceLookup(network, datacenter, service, tag string, connect bool, req, resp *dns.Msg, maxRecursionLevel int) {
  1112  	out, err := d.lookupServiceNodes(datacenter, service, tag, connect, maxRecursionLevel)
  1113  	if err != nil {
  1114  		d.logger.Printf("[ERR] dns: rpc error: %v", err)
  1115  		resp.SetRcode(req, dns.RcodeServerFailure)
  1116  		return
  1117  	}
  1118  
  1119  	// If we have no nodes, return not found!
  1120  	if len(out.Nodes) == 0 {
  1121  		d.addSOA(resp)
  1122  		resp.SetRcode(req, dns.RcodeNameError)
  1123  		return
  1124  	}
  1125  
  1126  	// Perform a random shuffle
  1127  	out.Nodes.Shuffle()
  1128  
  1129  	// Determine the TTL
  1130  	ttl, _ := d.GetTTLForService(service)
  1131  
  1132  	// Add various responses depending on the request
  1133  	qType := req.Question[0].Qtype
  1134  	if qType == dns.TypeSRV {
  1135  		d.serviceSRVRecords(datacenter, out.Nodes, req, resp, ttl, maxRecursionLevel)
  1136  	} else {
  1137  		d.serviceNodeRecords(datacenter, out.Nodes, req, resp, ttl, maxRecursionLevel)
  1138  	}
  1139  
  1140  	d.trimDNSResponse(network, req, resp)
  1141  
  1142  	// If the answer is empty and the response isn't truncated, return not found
  1143  	if len(resp.Answer) == 0 && !resp.Truncated {
  1144  		d.addSOA(resp)
  1145  		return
  1146  	}
  1147  }
  1148  
  1149  func ednsSubnetForRequest(req *dns.Msg) *dns.EDNS0_SUBNET {
  1150  	// IsEdns0 returns the EDNS RR if present or nil otherwise
  1151  	edns := req.IsEdns0()
  1152  
  1153  	if edns == nil {
  1154  		return nil
  1155  	}
  1156  
  1157  	for _, o := range edns.Option {
  1158  		if subnet, ok := o.(*dns.EDNS0_SUBNET); ok {
  1159  			return subnet
  1160  		}
  1161  	}
  1162  
  1163  	return nil
  1164  }
  1165  
  1166  // preparedQueryLookup is used to handle a prepared query.
  1167  func (d *DNSServer) preparedQueryLookup(network, datacenter, query string, remoteAddr net.Addr, req, resp *dns.Msg, maxRecursionLevel int) {
  1168  	// Execute the prepared query.
  1169  	args := structs.PreparedQueryExecuteRequest{
  1170  		Datacenter:    datacenter,
  1171  		QueryIDOrName: query,
  1172  		QueryOptions: structs.QueryOptions{
  1173  			Token:      d.agent.tokens.UserToken(),
  1174  			AllowStale: d.config.AllowStale,
  1175  			MaxAge:     d.config.CacheMaxAge,
  1176  		},
  1177  
  1178  		// Always pass the local agent through. In the DNS interface, there
  1179  		// is no provision for passing additional query parameters, so we
  1180  		// send the local agent's data through to allow distance sorting
  1181  		// relative to ourself on the server side.
  1182  		Agent: structs.QuerySource{
  1183  			Datacenter: d.agent.config.Datacenter,
  1184  			Segment:    d.agent.config.SegmentName,
  1185  			Node:       d.agent.config.NodeName,
  1186  		},
  1187  	}
  1188  
  1189  	subnet := ednsSubnetForRequest(req)
  1190  
  1191  	if subnet != nil {
  1192  		args.Source.Ip = subnet.Address.String()
  1193  	} else {
  1194  		switch v := remoteAddr.(type) {
  1195  		case *net.UDPAddr:
  1196  			args.Source.Ip = v.IP.String()
  1197  		case *net.TCPAddr:
  1198  			args.Source.Ip = v.IP.String()
  1199  		case *net.IPAddr:
  1200  			args.Source.Ip = v.IP.String()
  1201  		}
  1202  	}
  1203  
  1204  	out, err := d.lookupPreparedQuery(args)
  1205  
  1206  	// If they give a bogus query name, treat that as a name error,
  1207  	// not a full on server error. We have to use a string compare
  1208  	// here since the RPC layer loses the type information.
  1209  	if err != nil && err.Error() == consul.ErrQueryNotFound.Error() {
  1210  		d.addSOA(resp)
  1211  		resp.SetRcode(req, dns.RcodeNameError)
  1212  		return
  1213  	} else if err != nil {
  1214  		resp.SetRcode(req, dns.RcodeServerFailure)
  1215  		return
  1216  	}
  1217  
  1218  	// TODO (slackpad) - What's a safe limit we can set here? It seems like
  1219  	// with dup filtering done at this level we need to get everything to
  1220  	// match the previous behavior. We can optimize by pushing more filtering
  1221  	// into the query execution, but for now I think we need to get the full
  1222  	// response. We could also choose a large arbitrary number that will
  1223  	// likely work in practice, like 10*maxUDPAnswerLimit which should help
  1224  	// reduce bandwidth if there are thousands of nodes available.
  1225  
  1226  	// Determine the TTL. The parse should never fail since we vet it when
  1227  	// the query is created, but we check anyway. If the query didn't
  1228  	// specify a TTL then we will try to use the agent's service-specific
  1229  	// TTL configs.
  1230  	var ttl time.Duration
  1231  	if out.DNS.TTL != "" {
  1232  		var err error
  1233  		ttl, err = time.ParseDuration(out.DNS.TTL)
  1234  		if err != nil {
  1235  			d.logger.Printf("[WARN] dns: Failed to parse TTL '%s' for prepared query '%s', ignoring", out.DNS.TTL, query)
  1236  		}
  1237  	} else if d.config.ServiceTTL != nil {
  1238  		ttl, _ = d.GetTTLForService(out.Service)
  1239  	}
  1240  
  1241  	// If we have no nodes, return not found!
  1242  	if len(out.Nodes) == 0 {
  1243  		d.addSOA(resp)
  1244  		resp.SetRcode(req, dns.RcodeNameError)
  1245  		return
  1246  	}
  1247  
  1248  	// Add various responses depending on the request.
  1249  	qType := req.Question[0].Qtype
  1250  	if qType == dns.TypeSRV {
  1251  		d.serviceSRVRecords(out.Datacenter, out.Nodes, req, resp, ttl, maxRecursionLevel)
  1252  	} else {
  1253  		d.serviceNodeRecords(out.Datacenter, out.Nodes, req, resp, ttl, maxRecursionLevel)
  1254  	}
  1255  
  1256  	d.trimDNSResponse(network, req, resp)
  1257  
  1258  	// If the answer is empty and the response isn't truncated, return not found
  1259  	if len(resp.Answer) == 0 && !resp.Truncated {
  1260  		d.addSOA(resp)
  1261  		return
  1262  	}
  1263  }
  1264  
  1265  func (d *DNSServer) lookupPreparedQuery(args structs.PreparedQueryExecuteRequest) (*structs.PreparedQueryExecuteResponse, error) {
  1266  	var out structs.PreparedQueryExecuteResponse
  1267  
  1268  RPC:
  1269  	if d.config.UseCache {
  1270  		raw, m, err := d.agent.cache.Get(cachetype.PreparedQueryName, &args)
  1271  		if err != nil {
  1272  			return nil, err
  1273  		}
  1274  		reply, ok := raw.(*structs.PreparedQueryExecuteResponse)
  1275  		if !ok {
  1276  			// This should never happen, but we want to protect against panics
  1277  			return nil, err
  1278  		}
  1279  
  1280  		d.logger.Printf("[TRACE] dns: cache hit: %v for prepared query %s", m.Hit, args.QueryIDOrName)
  1281  
  1282  		out = *reply
  1283  	} else {
  1284  		if err := d.agent.RPC("PreparedQuery.Execute", &args, &out); err != nil {
  1285  			return nil, err
  1286  		}
  1287  	}
  1288  
  1289  	// Verify that request is not too stale, redo the request.
  1290  	if args.AllowStale {
  1291  		if out.LastContact > d.config.MaxStale {
  1292  			args.AllowStale = false
  1293  			d.logger.Printf("[WARN] dns: Query results too stale, re-requesting")
  1294  			goto RPC
  1295  		} else if out.LastContact > staleCounterThreshold {
  1296  			metrics.IncrCounter([]string{"dns", "stale_queries"}, 1)
  1297  		}
  1298  	}
  1299  
  1300  	return &out, nil
  1301  }
  1302  
  1303  // serviceNodeRecords is used to add the node records for a service lookup
  1304  func (d *DNSServer) serviceNodeRecords(dc string, nodes structs.CheckServiceNodes, req, resp *dns.Msg, ttl time.Duration, maxRecursionLevel int) {
  1305  	qName := req.Question[0].Name
  1306  	qType := req.Question[0].Qtype
  1307  	handled := make(map[string]struct{})
  1308  	edns := req.IsEdns0() != nil
  1309  	var answerCNAME []dns.RR = nil
  1310  
  1311  	count := 0
  1312  	for _, node := range nodes {
  1313  		// Start with the translated address but use the service address,
  1314  		// if specified.
  1315  		addr := d.agent.TranslateAddress(dc, node.Node.Address, node.Node.TaggedAddresses)
  1316  		if node.Service.Address != "" {
  1317  			addr = node.Service.Address
  1318  		}
  1319  
  1320  		// If the service address is a CNAME for the service we are looking
  1321  		// for then use the node address.
  1322  		if qName == strings.TrimSuffix(addr, ".")+"." {
  1323  			addr = node.Node.Address
  1324  		}
  1325  
  1326  		// Avoid duplicate entries, possible if a node has
  1327  		// the same service on multiple ports, etc.
  1328  		if _, ok := handled[addr]; ok {
  1329  			continue
  1330  		}
  1331  		handled[addr] = struct{}{}
  1332  
  1333  		generateMeta := false
  1334  		metaInAnswer := false
  1335  		if qType == dns.TypeANY || qType == dns.TypeTXT {
  1336  			generateMeta = true
  1337  			metaInAnswer = true
  1338  		} else if d.config.NodeMetaTXT {
  1339  			generateMeta = true
  1340  		}
  1341  
  1342  		// Add the node record
  1343  		had_answer := false
  1344  		records, meta := d.formatNodeRecord(node.Node, addr, qName, qType, ttl, edns, maxRecursionLevel, generateMeta)
  1345  		if records != nil {
  1346  			switch records[0].(type) {
  1347  			case *dns.CNAME:
  1348  				// keep track of the first CNAME + associated RRs but don't add to the resp.Answer yet
  1349  				// this will only be added if no non-CNAME RRs are found
  1350  				if len(answerCNAME) == 0 {
  1351  					answerCNAME = records
  1352  				}
  1353  			default:
  1354  				resp.Answer = append(resp.Answer, records...)
  1355  				had_answer = true
  1356  			}
  1357  		}
  1358  
  1359  		if meta != nil && generateMeta && metaInAnswer {
  1360  			resp.Answer = append(resp.Answer, meta...)
  1361  			had_answer = true
  1362  		} else if meta != nil && generateMeta {
  1363  			resp.Extra = append(resp.Extra, meta...)
  1364  		}
  1365  
  1366  		if had_answer {
  1367  			count++
  1368  			if count == d.config.ARecordLimit {
  1369  				// We stop only if greater than 0 or we reached the limit
  1370  				return
  1371  			}
  1372  		}
  1373  	}
  1374  
  1375  	if len(resp.Answer) == 0 && len(answerCNAME) > 0 {
  1376  		resp.Answer = answerCNAME
  1377  	}
  1378  }
  1379  
  1380  func findWeight(node structs.CheckServiceNode) int {
  1381  	// By default, when only_passing is false, warning and passing nodes are returned
  1382  	// Those values will be used if using a client with support while server has no
  1383  	// support for weights
  1384  	weightPassing := 1
  1385  	weightWarning := 1
  1386  	if node.Service.Weights != nil {
  1387  		weightPassing = node.Service.Weights.Passing
  1388  		weightWarning = node.Service.Weights.Warning
  1389  	}
  1390  	serviceChecks := make(api.HealthChecks, 0)
  1391  	for _, c := range node.Checks {
  1392  		if c.ServiceName == node.Service.Service || c.ServiceName == "" {
  1393  			healthCheck := &api.HealthCheck{
  1394  				Node:        c.Node,
  1395  				CheckID:     string(c.CheckID),
  1396  				Name:        c.Name,
  1397  				Status:      c.Status,
  1398  				Notes:       c.Notes,
  1399  				Output:      c.Output,
  1400  				ServiceID:   c.ServiceID,
  1401  				ServiceName: c.ServiceName,
  1402  				ServiceTags: c.ServiceTags,
  1403  			}
  1404  			serviceChecks = append(serviceChecks, healthCheck)
  1405  		}
  1406  	}
  1407  	status := serviceChecks.AggregatedStatus()
  1408  	switch status {
  1409  	case api.HealthWarning:
  1410  		return weightWarning
  1411  	case api.HealthPassing:
  1412  		return weightPassing
  1413  	case api.HealthMaint:
  1414  		// Not used in theory
  1415  		return 0
  1416  	case api.HealthCritical:
  1417  		// Should not happen since already filtered
  1418  		return 0
  1419  	default:
  1420  		// When non-standard status, return 1
  1421  		return 1
  1422  	}
  1423  }
  1424  
  1425  // serviceARecords is used to add the SRV records for a service lookup
  1426  func (d *DNSServer) serviceSRVRecords(dc string, nodes structs.CheckServiceNodes, req, resp *dns.Msg, ttl time.Duration, maxRecursionLevel int) {
  1427  	handled := make(map[string]struct{})
  1428  	edns := req.IsEdns0() != nil
  1429  
  1430  	for _, node := range nodes {
  1431  		// Avoid duplicate entries, possible if a node has
  1432  		// the same service the same port, etc.
  1433  		tuple := fmt.Sprintf("%s:%s:%d", node.Node.Node, node.Service.Address, node.Service.Port)
  1434  		if _, ok := handled[tuple]; ok {
  1435  			continue
  1436  		}
  1437  		handled[tuple] = struct{}{}
  1438  
  1439  		weight := findWeight(node)
  1440  		// Add the SRV record
  1441  		srvRec := &dns.SRV{
  1442  			Hdr: dns.RR_Header{
  1443  				Name:   req.Question[0].Name,
  1444  				Rrtype: dns.TypeSRV,
  1445  				Class:  dns.ClassINET,
  1446  				Ttl:    uint32(ttl / time.Second),
  1447  			},
  1448  			Priority: 1,
  1449  			Weight:   uint16(weight),
  1450  			Port:     uint16(node.Service.Port),
  1451  			Target:   fmt.Sprintf("%s.node.%s.%s", node.Node.Node, dc, d.domain),
  1452  		}
  1453  		resp.Answer = append(resp.Answer, srvRec)
  1454  
  1455  		// Start with the translated address but use the service address,
  1456  		// if specified.
  1457  		addr := d.agent.TranslateAddress(dc, node.Node.Address, node.Node.TaggedAddresses)
  1458  		if node.Service.Address != "" {
  1459  			addr = node.Service.Address
  1460  		}
  1461  
  1462  		// Add the extra record
  1463  		records, meta := d.formatNodeRecord(node.Node, addr, srvRec.Target, dns.TypeANY, ttl, edns, maxRecursionLevel, d.config.NodeMetaTXT)
  1464  		if len(records) > 0 {
  1465  			// Use the node address if it doesn't differ from the service address
  1466  			if addr == node.Node.Address {
  1467  				resp.Extra = append(resp.Extra, records...)
  1468  			} else {
  1469  				// If it differs from the service address, give a special response in the
  1470  				// 'addr.consul' domain with the service IP encoded in it. We have to do
  1471  				// this because we can't put an IP in the target field of an SRV record.
  1472  				switch record := records[0].(type) {
  1473  				// IPv4
  1474  				case *dns.A:
  1475  					addr := hex.EncodeToString(record.A)
  1476  
  1477  					// Take the last 8 chars (4 bytes) of the encoded address to avoid junk bytes
  1478  					srvRec.Target = fmt.Sprintf("%s.addr.%s.%s", addr[len(addr)-(net.IPv4len*2):], dc, d.domain)
  1479  					record.Hdr.Name = srvRec.Target
  1480  					resp.Extra = append(resp.Extra, record)
  1481  
  1482  				// IPv6
  1483  				case *dns.AAAA:
  1484  					srvRec.Target = fmt.Sprintf("%s.addr.%s.%s", hex.EncodeToString(record.AAAA), dc, d.domain)
  1485  					record.Hdr.Name = srvRec.Target
  1486  					resp.Extra = append(resp.Extra, record)
  1487  
  1488  				// Something else (probably a CNAME; just add the records).
  1489  				default:
  1490  					resp.Extra = append(resp.Extra, records...)
  1491  				}
  1492  			}
  1493  
  1494  			if meta != nil && d.config.NodeMetaTXT {
  1495  				resp.Extra = append(resp.Extra, meta...)
  1496  			}
  1497  		}
  1498  	}
  1499  }
  1500  
  1501  // handleRecurse is used to handle recursive DNS queries
  1502  func (d *DNSServer) handleRecurse(resp dns.ResponseWriter, req *dns.Msg) {
  1503  	q := req.Question[0]
  1504  	network := "udp"
  1505  	defer func(s time.Time) {
  1506  		d.logger.Printf("[DEBUG] dns: request for %v (%s) (%v) from client %s (%s)",
  1507  			q, network, time.Since(s), resp.RemoteAddr().String(),
  1508  			resp.RemoteAddr().Network())
  1509  	}(time.Now())
  1510  
  1511  	// Switch to TCP if the client is
  1512  	if _, ok := resp.RemoteAddr().(*net.TCPAddr); ok {
  1513  		network = "tcp"
  1514  	}
  1515  
  1516  	// Recursively resolve
  1517  	c := &dns.Client{Net: network, Timeout: d.config.RecursorTimeout}
  1518  	var r *dns.Msg
  1519  	var rtt time.Duration
  1520  	var err error
  1521  	for _, recursor := range d.recursors {
  1522  		r, rtt, err = c.Exchange(req, recursor)
  1523  		// Check if the response is valid and has the desired Response code
  1524  		if r != nil && (r.Rcode != dns.RcodeSuccess && r.Rcode != dns.RcodeNameError) {
  1525  			d.logger.Printf("[DEBUG] dns: recurse RTT for %v (%v) Recursor queried: %v Status returned: %v", q, rtt, recursor, dns.RcodeToString[r.Rcode])
  1526  			// If we still have recursors to forward the query to,
  1527  			// we move forward onto the next one else the loop ends
  1528  			continue
  1529  		} else if err == nil || err == dns.ErrTruncated {
  1530  			// Compress the response; we don't know if the incoming
  1531  			// response was compressed or not, so by not compressing
  1532  			// we might generate an invalid packet on the way out.
  1533  			r.Compress = !d.disableCompression.Load().(bool)
  1534  
  1535  			// Forward the response
  1536  			d.logger.Printf("[DEBUG] dns: recurse RTT for %v (%v) Recursor queried: %v", q, rtt, recursor)
  1537  			if err := resp.WriteMsg(r); err != nil {
  1538  				d.logger.Printf("[WARN] dns: failed to respond: %v", err)
  1539  			}
  1540  			return
  1541  		}
  1542  		d.logger.Printf("[ERR] dns: recurse failed: %v", err)
  1543  	}
  1544  
  1545  	// If all resolvers fail, return a SERVFAIL message
  1546  	d.logger.Printf("[ERR] dns: all resolvers failed for %v from client %s (%s)",
  1547  		q, resp.RemoteAddr().String(), resp.RemoteAddr().Network())
  1548  	m := &dns.Msg{}
  1549  	m.SetReply(req)
  1550  	m.Compress = !d.disableCompression.Load().(bool)
  1551  	m.RecursionAvailable = true
  1552  	m.SetRcode(req, dns.RcodeServerFailure)
  1553  	if edns := req.IsEdns0(); edns != nil {
  1554  		setEDNS(req, m, true)
  1555  	}
  1556  	resp.WriteMsg(m)
  1557  }
  1558  
  1559  // resolveCNAME is used to recursively resolve CNAME records
  1560  func (d *DNSServer) resolveCNAME(name string, maxRecursionLevel int) []dns.RR {
  1561  	// If the CNAME record points to a Consul address, resolve it internally
  1562  	// Convert query to lowercase because DNS is case insensitive; d.domain is
  1563  	// already converted
  1564  
  1565  	if strings.HasSuffix(strings.ToLower(name), "."+d.domain) {
  1566  		if maxRecursionLevel < 1 {
  1567  			d.logger.Printf("[ERR] dns: Infinite recursion detected for %s, won't perform any CNAME resolution.", name)
  1568  			return nil
  1569  		}
  1570  		req := &dns.Msg{}
  1571  		resp := &dns.Msg{}
  1572  
  1573  		req.SetQuestion(name, dns.TypeANY)
  1574  		d.doDispatch("udp", nil, req, resp, maxRecursionLevel-1)
  1575  
  1576  		return resp.Answer
  1577  	}
  1578  
  1579  	// Do nothing if we don't have a recursor
  1580  	if len(d.recursors) == 0 {
  1581  		return nil
  1582  	}
  1583  
  1584  	// Ask for any A records
  1585  	m := new(dns.Msg)
  1586  	m.SetQuestion(name, dns.TypeA)
  1587  
  1588  	// Make a DNS lookup request
  1589  	c := &dns.Client{Net: "udp", Timeout: d.config.RecursorTimeout}
  1590  	var r *dns.Msg
  1591  	var rtt time.Duration
  1592  	var err error
  1593  	for _, recursor := range d.recursors {
  1594  		r, rtt, err = c.Exchange(m, recursor)
  1595  		if err == nil {
  1596  			d.logger.Printf("[DEBUG] dns: cname recurse RTT for %v (%v)", name, rtt)
  1597  			return r.Answer
  1598  		}
  1599  		d.logger.Printf("[ERR] dns: cname recurse failed for %v: %v", name, err)
  1600  	}
  1601  	d.logger.Printf("[ERR] dns: all resolvers failed for %v", name)
  1602  	return nil
  1603  }