github.com/database64128/shadowsocks-go@v1.7.0/dns/dns.go (about)

     1  package dns
     2  
     3  import (
     4  	"encoding/binary"
     5  	"errors"
     6  	"fmt"
     7  	"io"
     8  	"math"
     9  	"net"
    10  	"net/netip"
    11  	"os"
    12  	"sync"
    13  	"time"
    14  
    15  	"github.com/database64128/shadowsocks-go/conn"
    16  	"github.com/database64128/shadowsocks-go/zerocopy"
    17  	"go.uber.org/zap"
    18  	"golang.org/x/net/dns/dnsmessage"
    19  )
    20  
    21  const (
    22  	// maxDNSPacketSize is the maximum packet size to advertise in EDNS(0).
    23  	// We use the same value as Go itself.
    24  	maxDNSPacketSize = 1232
    25  
    26  	lookupTimeout = 20 * time.Second
    27  )
    28  
    29  var ErrLookup = errors.New("name lookup failed")
    30  
    31  // ResolverConfig configures a DNS resolver.
    32  type ResolverConfig struct {
    33  	// Name is the resolver's name.
    34  	// The name must be unique among all resolvers.
    35  	Name string `json:"name"`
    36  
    37  	// AddrPort is the upstream server's address and port.
    38  	AddrPort netip.AddrPort `json:"addrPort"`
    39  
    40  	// TCPClientName is the name of the TCPClient to use.
    41  	// Leave empty to disable TCP.
    42  	TCPClientName string `json:"tcpClientName"`
    43  
    44  	// UDPClientName is the name of the UDPClient to use.
    45  	// Leave empty to disable UDP.
    46  	UDPClientName string `json:"udpClientName"`
    47  }
    48  
    49  func (rc *ResolverConfig) Resolver(tcpClientMap map[string]zerocopy.TCPClient, udpClientMap map[string]zerocopy.UDPClient, logger *zap.Logger) (*Resolver, error) {
    50  	var (
    51  		tcpClient zerocopy.TCPClient
    52  		udpClient zerocopy.UDPClient
    53  	)
    54  
    55  	if rc.TCPClientName != "" {
    56  		tcpClient = tcpClientMap[rc.TCPClientName]
    57  		if tcpClient == nil {
    58  			return nil, fmt.Errorf("unknown TCP client: %s", rc.TCPClientName)
    59  		}
    60  	}
    61  
    62  	if rc.UDPClientName != "" {
    63  		udpClient = udpClientMap[rc.UDPClientName]
    64  		if udpClient == nil {
    65  			return nil, fmt.Errorf("unknown UDP client: %s", rc.UDPClientName)
    66  		}
    67  	}
    68  
    69  	return NewResolver(rc.Name, rc.AddrPort, tcpClient, udpClient, logger), nil
    70  }
    71  
    72  // Result represents the result of name resolution.
    73  type Result struct {
    74  	IPv4 []netip.Addr
    75  	IPv6 []netip.Addr
    76  
    77  	// TTL is the minimum TTL of A and AAAA RRs.
    78  	TTL time.Time
    79  }
    80  
    81  type Resolver struct {
    82  	// name stores the resolver's name to make its log messages more useful.
    83  	name string
    84  
    85  	// mu protects the DNS cache map.
    86  	mu sync.RWMutex
    87  
    88  	// cache is the DNS cache map.
    89  	cache map[string]Result
    90  
    91  	// serverAddr is the upstream server's address and port.
    92  	serverAddr conn.Addr
    93  
    94  	// serverAddrPort is the upstream server's address and port.
    95  	serverAddrPort netip.AddrPort
    96  
    97  	// tcpClient is the TCPClient to use for sending queries and receiving replies.
    98  	tcpClient zerocopy.TCPClient
    99  
   100  	// udpClient is the UDPClient to use for sending queries and receiving replies.
   101  	udpClient zerocopy.UDPClient
   102  
   103  	// logger is the shared logger instance.
   104  	logger *zap.Logger
   105  }
   106  
   107  func NewResolver(name string, serverAddrPort netip.AddrPort, tcpClient zerocopy.TCPClient, udpClient zerocopy.UDPClient, logger *zap.Logger) *Resolver {
   108  	return &Resolver{
   109  		name:           name,
   110  		cache:          make(map[string]Result),
   111  		serverAddr:     conn.AddrFromIPPort(serverAddrPort),
   112  		serverAddrPort: serverAddrPort,
   113  		tcpClient:      tcpClient,
   114  		udpClient:      udpClient,
   115  		logger:         logger,
   116  	}
   117  }
   118  
   119  func (r *Resolver) Lookup(name string) (Result, error) {
   120  	// Lookup cache first.
   121  	r.mu.RLock()
   122  	result, ok := r.cache[name]
   123  	r.mu.RUnlock()
   124  
   125  	if ok && result.TTL.After(time.Now()) {
   126  		if ce := r.logger.Check(zap.DebugLevel, "DNS lookup got result from cache"); ce != nil {
   127  			ce.Write(
   128  				zap.String("resolver", r.name),
   129  				zap.String("name", name),
   130  				zap.Time("ttl", result.TTL),
   131  				zap.Stringers("v4", result.IPv4),
   132  				zap.Stringers("v6", result.IPv6),
   133  			)
   134  		}
   135  		return result, nil
   136  	}
   137  
   138  	// Send queries to upstream server.
   139  	return r.sendQueries(name)
   140  }
   141  
   142  func (r *Resolver) sendQueries(nameString string) (result Result, err error) {
   143  	name, err := dnsmessage.NewName(nameString + ".")
   144  	if err != nil {
   145  		return
   146  	}
   147  
   148  	var (
   149  		rh dnsmessage.ResourceHeader
   150  		rb dnsmessage.OPTResource
   151  	)
   152  
   153  	err = rh.SetEDNS0(maxDNSPacketSize, dnsmessage.RCodeSuccess, false)
   154  	if err != nil {
   155  		return
   156  	}
   157  
   158  	qBuf := make([]byte, 2+512+2+512)
   159  
   160  	q4 := dnsmessage.Message{
   161  		Header: dnsmessage.Header{
   162  			ID:               4,
   163  			RecursionDesired: true,
   164  		},
   165  		Questions: []dnsmessage.Question{
   166  			{
   167  				Name:  name,
   168  				Type:  dnsmessage.TypeA,
   169  				Class: dnsmessage.ClassINET,
   170  			},
   171  		},
   172  		Additionals: []dnsmessage.Resource{
   173  			{
   174  				Header: rh,
   175  				Body:   &rb,
   176  			},
   177  		},
   178  	}
   179  	q4Pkt := qBuf[2:2]
   180  	q4Pkt, err = q4.AppendPack(q4Pkt)
   181  	if err != nil {
   182  		return
   183  	}
   184  	q4PktEnd := 2 + len(q4Pkt)
   185  
   186  	q6 := dnsmessage.Message{
   187  		Header: dnsmessage.Header{
   188  			ID:               6,
   189  			RecursionDesired: true,
   190  		},
   191  		Questions: []dnsmessage.Question{
   192  			{
   193  				Name:  name,
   194  				Type:  dnsmessage.TypeAAAA,
   195  				Class: dnsmessage.ClassINET,
   196  			},
   197  		},
   198  		Additionals: []dnsmessage.Resource{
   199  			{
   200  				Header: rh,
   201  				Body:   &rb,
   202  			},
   203  		},
   204  	}
   205  	q6PktStart := q4PktEnd + 2
   206  	q6Pkt := qBuf[q6PktStart:q6PktStart]
   207  	q6Pkt, err = q6.AppendPack(q6Pkt)
   208  	if err != nil {
   209  		return
   210  	}
   211  	q6PktEnd := q6PktStart + len(q6Pkt)
   212  
   213  	var (
   214  		minTTL  uint32
   215  		handled bool
   216  	)
   217  
   218  	// Try UDP first if available.
   219  	if r.udpClient != nil {
   220  		result, minTTL, handled = r.sendQueriesUDP(nameString, q4Pkt, q6Pkt)
   221  
   222  		if ce := r.logger.Check(zap.DebugLevel, "DNS lookup sent queries via UDP"); ce != nil {
   223  			ce.Write(
   224  				zap.String("resolver", r.name),
   225  				zap.String("name", nameString),
   226  				zap.Uint32("minTTL", minTTL),
   227  				zap.Bool("handled", handled),
   228  				zap.Stringers("v4", result.IPv4),
   229  				zap.Stringers("v6", result.IPv6),
   230  			)
   231  		}
   232  	}
   233  
   234  	// Fallback to TCP if UDP failed or is unavailable.
   235  	if !handled && r.tcpClient != nil {
   236  		// Write length fields.
   237  		q4LenBuf := qBuf[:2]
   238  		q6LenBuf := qBuf[q4PktEnd:q6PktStart]
   239  		binary.BigEndian.PutUint16(q4LenBuf, uint16(len(q4Pkt)))
   240  		binary.BigEndian.PutUint16(q6LenBuf, uint16(len(q6Pkt)))
   241  
   242  		result, minTTL, handled = r.sendQueriesTCP(nameString, qBuf[:q6PktEnd])
   243  
   244  		if ce := r.logger.Check(zap.DebugLevel, "DNS lookup sent queries via TCP"); ce != nil {
   245  			ce.Write(
   246  				zap.String("resolver", r.name),
   247  				zap.String("name", nameString),
   248  				zap.Uint32("minTTL", minTTL),
   249  				zap.Bool("handled", handled),
   250  				zap.Stringers("v4", result.IPv4),
   251  				zap.Stringers("v6", result.IPv6),
   252  			)
   253  		}
   254  	}
   255  
   256  	if !handled {
   257  		err = ErrLookup
   258  		return
   259  	}
   260  
   261  	// Add result to cache if minTTL != 0.
   262  	if minTTL != 0 {
   263  		result.TTL = time.Now().Add(time.Duration(minTTL) * time.Second)
   264  
   265  		r.mu.Lock()
   266  		r.cache[nameString] = result
   267  		r.mu.Unlock()
   268  	}
   269  
   270  	return
   271  }
   272  
   273  // sendQueriesUDP sends queries using the resolver's UDP client and returns the result, a detached minTTL,
   274  // and whether the lookup was successful.
   275  //
   276  // It's the caller's responsibility to examine the minTTL and decide whether to cache the result.
   277  func (r *Resolver) sendQueriesUDP(nameString string, q4Pkt, q6Pkt []byte) (result Result, minTTL uint32, handled bool) {
   278  	// Create client session.
   279  	clientInfo, packer, unpacker, err := r.udpClient.NewSession()
   280  	if err != nil {
   281  		r.logger.Warn("Failed to create new UDP client session",
   282  			zap.String("resolver", r.name),
   283  			zap.Error(err),
   284  		)
   285  		return
   286  	}
   287  
   288  	packerInfo := packer.ClientPackerInfo()
   289  
   290  	// Prepare UDP socket.
   291  	udpConn, err := conn.ListenUDP(clientInfo.ListenConfig, "udp", "")
   292  	if err != nil {
   293  		r.logger.Warn("Failed to create UDP socket for DNS lookup",
   294  			zap.String("resolver", r.name),
   295  			zap.Error(err),
   296  		)
   297  		return
   298  	}
   299  	defer udpConn.Close()
   300  
   301  	// Set read deadline.
   302  	err = udpConn.SetReadDeadline(time.Now().Add(lookupTimeout))
   303  	if err != nil {
   304  		r.logger.Warn("Failed to set read deadline",
   305  			zap.String("resolver", r.name),
   306  			zap.Error(err),
   307  		)
   308  		return
   309  	}
   310  
   311  	// Spin up senders.
   312  	// Each sender will keep sending at 2s intervals until the stop signal
   313  	// is received or after 10 iterations.
   314  	sendFunc := func(pkt []byte, ctrlCh <-chan struct{}) {
   315  		b := make([]byte, packerInfo.Headroom.Front+len(pkt)+packerInfo.Headroom.Rear)
   316  
   317  	write:
   318  		for i := 0; i < 10; i++ {
   319  			copy(b[packerInfo.Headroom.Front:], pkt)
   320  			destAddrPort, packetStart, packetLength, err := packer.PackInPlace(b, r.serverAddr, packerInfo.Headroom.Front, len(pkt))
   321  			if err != nil {
   322  				r.logger.Warn("Failed to pack packet",
   323  					zap.String("resolver", r.name),
   324  					zap.String("name", nameString),
   325  					zap.Stringer("serverAddrPort", r.serverAddrPort),
   326  					zap.Error(err),
   327  				)
   328  				goto cleanup
   329  			}
   330  
   331  			_, err = udpConn.WriteToUDPAddrPort(b[packetStart:packetStart+packetLength], destAddrPort)
   332  			if err != nil {
   333  				r.logger.Warn("Failed to write query",
   334  					zap.String("resolver", r.name),
   335  					zap.String("name", nameString),
   336  					zap.Stringer("serverAddrPort", r.serverAddrPort),
   337  					zap.Stringer("destAddrPort", destAddrPort),
   338  					zap.Error(err),
   339  				)
   340  				goto cleanup
   341  			}
   342  
   343  			time.Sleep(2 * time.Second)
   344  
   345  			select {
   346  			case <-ctrlCh:
   347  				break write
   348  			default:
   349  				continue write
   350  			}
   351  
   352  		cleanup:
   353  			err = udpConn.SetReadDeadline(time.Now())
   354  			if err != nil {
   355  				r.logger.Warn("Failed to set read deadline",
   356  					zap.String("resolver", r.name),
   357  					zap.String("name", nameString),
   358  					zap.Stringer("serverAddrPort", r.serverAddrPort),
   359  					zap.Stringer("destAddrPort", destAddrPort),
   360  					zap.Error(err),
   361  				)
   362  			}
   363  			break
   364  		}
   365  	}
   366  
   367  	ctrlCh4 := make(chan struct{}, 1)
   368  	ctrlCh6 := make(chan struct{}, 1)
   369  	go sendFunc(q4Pkt, ctrlCh4)
   370  	go sendFunc(q6Pkt, ctrlCh6)
   371  
   372  	// Receive replies.
   373  	minTTL = math.MaxUint32
   374  	recvBuf := make([]byte, clientInfo.MaxPacketSize)
   375  
   376  	var (
   377  		v4done, v6done bool
   378  		parser         dnsmessage.Parser
   379  	)
   380  
   381  read:
   382  	for {
   383  		n, _, flags, packetSourceAddress, err := udpConn.ReadMsgUDPAddrPort(recvBuf, nil)
   384  		if err != nil {
   385  			if errors.Is(err, os.ErrDeadlineExceeded) {
   386  				r.logger.Warn("DNS lookup via UDP timed out",
   387  					zap.String("resolver", r.name),
   388  					zap.String("name", nameString),
   389  					zap.Stringer("serverAddrPort", r.serverAddrPort),
   390  				)
   391  				break
   392  			}
   393  			r.logger.Warn("Failed to read query response",
   394  				zap.String("resolver", r.name),
   395  				zap.String("name", nameString),
   396  				zap.Stringer("serverAddrPort", r.serverAddrPort),
   397  				zap.Stringer("packetSourceAddress", packetSourceAddress),
   398  				zap.Int("packetLength", n),
   399  				zap.Error(err),
   400  			)
   401  			continue
   402  		}
   403  		if err = conn.ParseFlagsForError(flags); err != nil {
   404  			r.logger.Warn("Failed to read query response",
   405  				zap.String("resolver", r.name),
   406  				zap.String("name", nameString),
   407  				zap.Stringer("serverAddrPort", r.serverAddrPort),
   408  				zap.Stringer("packetSourceAddress", packetSourceAddress),
   409  				zap.Int("packetLength", n),
   410  				zap.Error(err),
   411  			)
   412  			continue
   413  		}
   414  
   415  		payloadSourceAddrPort, payloadStart, payloadLength, err := unpacker.UnpackInPlace(recvBuf, packetSourceAddress, 0, n)
   416  		if err != nil {
   417  			r.logger.Warn("Failed to unpack packet",
   418  				zap.String("resolver", r.name),
   419  				zap.String("name", nameString),
   420  				zap.Stringer("serverAddrPort", r.serverAddrPort),
   421  				zap.Stringer("packetSourceAddress", packetSourceAddress),
   422  				zap.Int("packetLength", n),
   423  				zap.Error(err),
   424  			)
   425  			continue
   426  		}
   427  		if !conn.AddrPortMappedEqual(payloadSourceAddrPort, r.serverAddrPort) {
   428  			r.logger.Warn("Ignoring packet from unknown server",
   429  				zap.String("resolver", r.name),
   430  				zap.String("name", nameString),
   431  				zap.Stringer("serverAddrPort", r.serverAddrPort),
   432  				zap.Stringer("payloadSourceAddrPort", payloadSourceAddrPort),
   433  			)
   434  			continue
   435  		}
   436  		payload := recvBuf[payloadStart : payloadStart+payloadLength]
   437  
   438  		// Parse header.
   439  		header, err := parser.Start(payload)
   440  		if err != nil {
   441  			r.logger.Warn("Failed to parse query response header",
   442  				zap.String("resolver", r.name),
   443  				zap.String("name", nameString),
   444  				zap.Stringer("serverAddrPort", r.serverAddrPort),
   445  				zap.Error(err),
   446  			)
   447  			break
   448  		}
   449  
   450  		// Check transaction ID.
   451  		switch header.ID {
   452  		case 4:
   453  			if v4done {
   454  				continue
   455  			}
   456  		case 6:
   457  			if v6done {
   458  				continue
   459  			}
   460  		default:
   461  			r.logger.Warn("Unexpected transaction ID",
   462  				zap.String("resolver", r.name),
   463  				zap.String("name", nameString),
   464  				zap.Stringer("serverAddrPort", r.serverAddrPort),
   465  				zap.Uint16("transactionID", header.ID),
   466  			)
   467  			break read
   468  		}
   469  
   470  		// Check response bit.
   471  		if !header.Response {
   472  			r.logger.Warn("Received non-response reply",
   473  				zap.String("resolver", r.name),
   474  				zap.String("name", nameString),
   475  				zap.Stringer("serverAddrPort", r.serverAddrPort),
   476  			)
   477  			break
   478  		}
   479  
   480  		// Check truncated bit.
   481  		if header.Truncated {
   482  			r.logger.Warn("Received truncated reply",
   483  				zap.String("resolver", r.name),
   484  				zap.String("name", nameString),
   485  				zap.Stringer("serverAddrPort", r.serverAddrPort),
   486  			)
   487  			break
   488  		}
   489  
   490  		// Check RCode.
   491  		if header.RCode != dnsmessage.RCodeSuccess {
   492  			r.logger.Warn("DNS failure",
   493  				zap.String("resolver", r.name),
   494  				zap.String("name", nameString),
   495  				zap.Stringer("serverAddrPort", r.serverAddrPort),
   496  				zap.Stringer("RCode", header.RCode),
   497  			)
   498  			break
   499  		}
   500  
   501  		// Skip questions.
   502  		err = parser.SkipAllQuestions()
   503  		if err != nil {
   504  			r.logger.Warn("Failed to skip questions",
   505  				zap.String("resolver", r.name),
   506  				zap.String("name", nameString),
   507  				zap.Stringer("serverAddrPort", r.serverAddrPort),
   508  				zap.Error(err),
   509  			)
   510  			break
   511  		}
   512  
   513  		// Parse answers and add to result.
   514  		for {
   515  			answerHeader, err := parser.AnswerHeader()
   516  			if err != nil {
   517  				if err == dnsmessage.ErrSectionDone {
   518  					break
   519  				}
   520  				r.logger.Warn("Failed to parse answer header",
   521  					zap.String("resolver", r.name),
   522  					zap.String("name", nameString),
   523  					zap.Stringer("serverAddrPort", r.serverAddrPort),
   524  					zap.Error(err),
   525  				)
   526  				break read
   527  			}
   528  
   529  			// Set minimum TTL.
   530  			if answerHeader.TTL < minTTL {
   531  				if ce := r.logger.Check(zap.DebugLevel, "Updating minimum TTL"); ce != nil {
   532  					ce.Write(
   533  						zap.String("resolver", r.name),
   534  						zap.String("name", nameString),
   535  						zap.Stringer("serverAddrPort", r.serverAddrPort),
   536  						zap.Stringer("answerType", answerHeader.Type),
   537  						zap.Uint32("oldMinTTL", minTTL),
   538  						zap.Uint32("newMinTTL", answerHeader.TTL),
   539  					)
   540  				}
   541  				minTTL = answerHeader.TTL
   542  			}
   543  
   544  			// Skip non-A/AAAA RRs.
   545  			switch answerHeader.Type {
   546  			case dnsmessage.TypeA:
   547  				arr, err := parser.AResource()
   548  				if err != nil {
   549  					r.logger.Warn("Failed to parse A resource",
   550  						zap.String("resolver", r.name),
   551  						zap.String("name", nameString),
   552  						zap.Stringer("serverAddrPort", r.serverAddrPort),
   553  						zap.Error(err),
   554  					)
   555  					break read
   556  				}
   557  
   558  				addr4 := netip.AddrFrom4(arr.A)
   559  				result.IPv4 = append(result.IPv4, addr4)
   560  
   561  				if ce := r.logger.Check(zap.DebugLevel, "Processing A RR"); ce != nil {
   562  					ce.Write(
   563  						zap.String("resolver", r.name),
   564  						zap.String("name", nameString),
   565  						zap.Stringer("serverAddrPort", r.serverAddrPort),
   566  						zap.Stringer("addr", addr4),
   567  					)
   568  				}
   569  
   570  			case dnsmessage.TypeAAAA:
   571  				aaaarr, err := parser.AAAAResource()
   572  				if err != nil {
   573  					r.logger.Warn("Failed to parse AAAA resource",
   574  						zap.String("resolver", r.name),
   575  						zap.String("name", nameString),
   576  						zap.Stringer("serverAddrPort", r.serverAddrPort),
   577  						zap.Error(err),
   578  					)
   579  					break read
   580  				}
   581  
   582  				addr6 := netip.AddrFrom16(aaaarr.AAAA)
   583  				result.IPv6 = append(result.IPv6, addr6)
   584  
   585  				if ce := r.logger.Check(zap.DebugLevel, "Processing AAAA RR"); ce != nil {
   586  					ce.Write(
   587  						zap.String("resolver", r.name),
   588  						zap.String("name", nameString),
   589  						zap.Stringer("serverAddrPort", r.serverAddrPort),
   590  						zap.Stringer("addr", addr6),
   591  					)
   592  				}
   593  
   594  			default:
   595  				err = parser.SkipAnswer()
   596  				if err != nil {
   597  					r.logger.Warn("Failed to skip answer",
   598  						zap.String("resolver", r.name),
   599  						zap.String("name", nameString),
   600  						zap.Stringer("serverAddrPort", r.serverAddrPort),
   601  						zap.Stringer("answerType", answerHeader.Type),
   602  						zap.Error(err),
   603  					)
   604  					break read
   605  				}
   606  			}
   607  		}
   608  
   609  		// Stop corresponding sender and mark as done.
   610  		switch header.ID {
   611  		case 4:
   612  			ctrlCh4 <- struct{}{}
   613  			close(ctrlCh4)
   614  			v4done = true
   615  		case 6:
   616  			ctrlCh6 <- struct{}{}
   617  			close(ctrlCh6)
   618  			v6done = true
   619  		}
   620  
   621  		// Break out of loop if both v4 and v6 are done.
   622  		if v4done && v6done {
   623  			break
   624  		}
   625  	}
   626  
   627  	// Clean up in case of error.
   628  	if !v4done {
   629  		ctrlCh4 <- struct{}{}
   630  		close(ctrlCh4)
   631  	}
   632  	if !v6done {
   633  		ctrlCh6 <- struct{}{}
   634  		close(ctrlCh6)
   635  	}
   636  
   637  	handled = v4done && v6done
   638  	return
   639  }
   640  
   641  // sendQueriesTCP sends queries using the resolver's TCP client and returns the result, a detached minTTL,
   642  // and whether the lookup was successful.
   643  //
   644  // It's the caller's responsibility to examine the minTTL and decide whether to cache the result.
   645  func (r *Resolver) sendQueriesTCP(nameString string, queries []byte) (result Result, minTTL uint32, handled bool) {
   646  	// Write.
   647  	rawRW, rw, err := r.tcpClient.Dial(r.serverAddr, queries)
   648  	if err != nil {
   649  		r.logger.Warn("Failed to dial DNS server",
   650  			zap.String("resolver", r.name),
   651  			zap.String("name", nameString),
   652  			zap.Stringer("serverAddrPort", r.serverAddrPort),
   653  			zap.Error(err),
   654  		)
   655  		return
   656  	}
   657  	defer rawRW.Close()
   658  
   659  	// Set read deadline.
   660  	if tc, ok := rawRW.(*net.TCPConn); ok {
   661  		if err = tc.SetReadDeadline(time.Now().Add(lookupTimeout)); err != nil {
   662  			r.logger.Warn("Failed to set read deadline",
   663  				zap.String("resolver", r.name),
   664  				zap.String("name", nameString),
   665  				zap.Stringer("serverAddrPort", r.serverAddrPort),
   666  				zap.Error(err),
   667  			)
   668  			return
   669  		}
   670  	}
   671  
   672  	// Read.
   673  	crw := zerocopy.NewCopyReadWriter(rw)
   674  	lengthBuf := make([]byte, 2)
   675  	minTTL = math.MaxUint32
   676  
   677  	var (
   678  		v4done, v6done bool
   679  		parser         dnsmessage.Parser
   680  	)
   681  
   682  	for i := 0; i < 2; i++ {
   683  		// Read length field.
   684  		_, err = io.ReadFull(crw, lengthBuf)
   685  		if err != nil {
   686  			r.logger.Warn("Failed to read DNS response length",
   687  				zap.String("resolver", r.name),
   688  				zap.String("name", nameString),
   689  				zap.Stringer("serverAddrPort", r.serverAddrPort),
   690  				zap.Error(err),
   691  			)
   692  			return
   693  		}
   694  
   695  		msgLen := binary.BigEndian.Uint16(lengthBuf)
   696  		if msgLen == 0 {
   697  			r.logger.Warn("DNS response length is zero",
   698  				zap.String("resolver", r.name),
   699  				zap.String("name", nameString),
   700  				zap.Stringer("serverAddrPort", r.serverAddrPort),
   701  			)
   702  			return
   703  		}
   704  
   705  		// Read message.
   706  		msg := make([]byte, msgLen)
   707  		_, err = io.ReadFull(crw, msg)
   708  		if err != nil {
   709  			r.logger.Warn("Failed to read DNS response",
   710  				zap.String("resolver", r.name),
   711  				zap.String("name", nameString),
   712  				zap.Stringer("serverAddrPort", r.serverAddrPort),
   713  				zap.Error(err),
   714  			)
   715  			return
   716  		}
   717  
   718  		// Parse header.
   719  		header, err := parser.Start(msg)
   720  		if err != nil {
   721  			r.logger.Warn("Failed to parse query response header",
   722  				zap.String("resolver", r.name),
   723  				zap.String("name", nameString),
   724  				zap.Stringer("serverAddrPort", r.serverAddrPort),
   725  				zap.Error(err),
   726  			)
   727  			return
   728  		}
   729  
   730  		// Check transaction ID.
   731  		switch header.ID {
   732  		case 4, 6:
   733  		default:
   734  			r.logger.Warn("Unexpected transaction ID",
   735  				zap.String("resolver", r.name),
   736  				zap.String("name", nameString),
   737  				zap.Stringer("serverAddrPort", r.serverAddrPort),
   738  				zap.Uint16("transactionID", header.ID),
   739  			)
   740  			return
   741  		}
   742  
   743  		// Check response bit.
   744  		if !header.Response {
   745  			r.logger.Warn("Received non-response reply",
   746  				zap.String("resolver", r.name),
   747  				zap.String("name", nameString),
   748  				zap.Stringer("serverAddrPort", r.serverAddrPort),
   749  			)
   750  			return
   751  		}
   752  
   753  		// Check RCode.
   754  		if header.RCode != dnsmessage.RCodeSuccess {
   755  			r.logger.Warn("DNS failure",
   756  				zap.String("resolver", r.name),
   757  				zap.String("name", nameString),
   758  				zap.Stringer("serverAddrPort", r.serverAddrPort),
   759  				zap.Stringer("RCode", header.RCode),
   760  			)
   761  			return
   762  		}
   763  
   764  		// Skip questions.
   765  		err = parser.SkipAllQuestions()
   766  		if err != nil {
   767  			r.logger.Warn("Failed to skip questions",
   768  				zap.String("resolver", r.name),
   769  				zap.String("name", nameString),
   770  				zap.Stringer("serverAddrPort", r.serverAddrPort),
   771  				zap.Error(err),
   772  			)
   773  			return
   774  		}
   775  
   776  		// Parse answers and add to result.
   777  		for {
   778  			answerHeader, err := parser.AnswerHeader()
   779  			if err != nil {
   780  				if err == dnsmessage.ErrSectionDone {
   781  					break
   782  				}
   783  				r.logger.Warn("Failed to parse answer header",
   784  					zap.String("resolver", r.name),
   785  					zap.String("name", nameString),
   786  					zap.Stringer("serverAddrPort", r.serverAddrPort),
   787  					zap.Error(err),
   788  				)
   789  				return
   790  			}
   791  
   792  			// Set minimum TTL.
   793  			if answerHeader.TTL < minTTL {
   794  				if ce := r.logger.Check(zap.DebugLevel, "Updating minimum TTL"); ce != nil {
   795  					ce.Write(
   796  						zap.String("resolver", r.name),
   797  						zap.String("name", nameString),
   798  						zap.Stringer("serverAddrPort", r.serverAddrPort),
   799  						zap.Stringer("answerType", answerHeader.Type),
   800  						zap.Uint32("oldMinTTL", minTTL),
   801  						zap.Uint32("newMinTTL", answerHeader.TTL),
   802  					)
   803  				}
   804  				minTTL = answerHeader.TTL
   805  			}
   806  
   807  			// Skip non-A/AAAA RRs.
   808  			switch answerHeader.Type {
   809  			case dnsmessage.TypeA:
   810  				arr, err := parser.AResource()
   811  				if err != nil {
   812  					r.logger.Warn("Failed to parse A resource",
   813  						zap.String("resolver", r.name),
   814  						zap.String("name", nameString),
   815  						zap.Stringer("serverAddrPort", r.serverAddrPort),
   816  						zap.Error(err),
   817  					)
   818  					return
   819  				}
   820  
   821  				addr4 := netip.AddrFrom4(arr.A)
   822  				result.IPv4 = append(result.IPv4, addr4)
   823  
   824  				if ce := r.logger.Check(zap.DebugLevel, "Processing A RR"); ce != nil {
   825  					ce.Write(
   826  						zap.String("resolver", r.name),
   827  						zap.String("name", nameString),
   828  						zap.Stringer("serverAddrPort", r.serverAddrPort),
   829  						zap.Stringer("addr", addr4),
   830  					)
   831  				}
   832  
   833  			case dnsmessage.TypeAAAA:
   834  				aaaarr, err := parser.AAAAResource()
   835  				if err != nil {
   836  					r.logger.Warn("Failed to parse AAAA resource",
   837  						zap.String("resolver", r.name),
   838  						zap.String("name", nameString),
   839  						zap.Stringer("serverAddrPort", r.serverAddrPort),
   840  						zap.Error(err),
   841  					)
   842  					return
   843  				}
   844  
   845  				addr6 := netip.AddrFrom16(aaaarr.AAAA)
   846  				result.IPv6 = append(result.IPv6, addr6)
   847  
   848  				if ce := r.logger.Check(zap.DebugLevel, "Processing AAAA RR"); ce != nil {
   849  					ce.Write(
   850  						zap.String("resolver", r.name),
   851  						zap.String("name", nameString),
   852  						zap.Stringer("serverAddrPort", r.serverAddrPort),
   853  						zap.Stringer("addr", addr6),
   854  					)
   855  				}
   856  
   857  			default:
   858  				err = parser.SkipAnswer()
   859  				if err != nil {
   860  					r.logger.Warn("Failed to skip answer",
   861  						zap.String("resolver", r.name),
   862  						zap.String("name", nameString),
   863  						zap.Stringer("serverAddrPort", r.serverAddrPort),
   864  						zap.Stringer("answerType", answerHeader.Type),
   865  						zap.Error(err),
   866  					)
   867  					return
   868  				}
   869  			}
   870  		}
   871  
   872  		// Mark v4 or v6 as done.
   873  		switch header.ID {
   874  		case 4:
   875  			v4done = true
   876  		case 6:
   877  			v6done = true
   878  		}
   879  	}
   880  
   881  	handled = v4done && v6done
   882  	return
   883  }