github.com/yaling888/clash@v1.53.0/listener/tun/ipstack/commons/dns.go (about)

     1  package commons
     2  
     3  import (
     4  	"net/netip"
     5  	"time"
     6  
     7  	D "github.com/miekg/dns"
     8  
     9  	"github.com/yaling888/clash/component/resolver"
    10  	C "github.com/yaling888/clash/constant"
    11  )
    12  
    13  const ipv6Delay = time.Millisecond * 6 // delay response AAAA answer when disable IPv6
    14  
    15  func ShouldHijackDns(dnsHijack []C.DNSUrl, targetAddr netip.AddrPort, network string) bool {
    16  	for _, dns := range dnsHijack {
    17  		if dns.Network == network && (dns.AddrPort.AddrPort == targetAddr ||
    18  			(dns.AddrPort.Addr().IsUnspecified() && dns.AddrPort.Port() == targetAddr.Port())) {
    19  			return true
    20  		}
    21  	}
    22  	return false
    23  }
    24  
    25  func RelayDnsPacket(payload []byte) ([]byte, error) {
    26  	msg := &D.Msg{}
    27  	if err := msg.Unpack(payload); err != nil {
    28  		return nil, err
    29  	}
    30  
    31  	if len(msg.Question) == 0 {
    32  		return handleMsgWithEmptyAnswer(msg, D.RcodeBadName)
    33  	}
    34  
    35  	if resolver.DisableIPv6 && msg.Question[0].Qtype == D.TypeAAAA {
    36  		time.Sleep(ipv6Delay)
    37  		return handleMsgWithEmptyAnswer(msg, D.RcodeSuccess)
    38  	}
    39  
    40  	r, err := resolver.ServeMsg(msg)
    41  	if err != nil {
    42  		return handleMsgWithEmptyAnswer(msg, D.RcodeServerFailure)
    43  	}
    44  
    45  	r.SetRcode(msg, r.Rcode)
    46  	r.Compress = true
    47  	return r.Pack()
    48  }
    49  
    50  func handleMsgWithEmptyAnswer(r *D.Msg, code int) ([]byte, error) {
    51  	msg := &D.Msg{}
    52  	msg.Answer = []D.RR{}
    53  
    54  	msg.SetRcode(r, code)
    55  	msg.Authoritative = true
    56  	msg.RecursionAvailable = true
    57  
    58  	return msg.Pack()
    59  }