github.com/igoogolx/clash@v1.19.8/dns/server.go (about)

     1  package dns
     2  
     3  import (
     4  	"errors"
     5  	"net"
     6  
     7  	"github.com/igoogolx/clash/common/sockopt"
     8  	"github.com/igoogolx/clash/context"
     9  	"github.com/igoogolx/clash/log"
    10  
    11  	D "github.com/miekg/dns"
    12  )
    13  
    14  var (
    15  	address string
    16  	server  = &Server{}
    17  
    18  	dnsDefaultTTL uint32 = 600
    19  )
    20  
    21  type Server struct {
    22  	*D.Server
    23  	handler handler
    24  }
    25  
    26  // ServeDNS implement D.Handler ServeDNS
    27  func (s *Server) ServeDNS(w D.ResponseWriter, r *D.Msg) {
    28  	msg, err := handlerWithContext(s.handler, r)
    29  	if err != nil {
    30  		D.HandleFailed(w, r)
    31  		return
    32  	}
    33  	msg.Compress = true
    34  	w.WriteMsg(msg)
    35  }
    36  
    37  func handlerWithContext(handler handler, msg *D.Msg) (*D.Msg, error) {
    38  	if len(msg.Question) == 0 {
    39  		return nil, errors.New("at least one question is required")
    40  	}
    41  
    42  	ctx := context.NewDNSContext(msg)
    43  	return handler(ctx, msg)
    44  }
    45  
    46  func (s *Server) setHandler(handler handler) {
    47  	s.handler = handler
    48  }
    49  
    50  func ReCreateServer(addr string, resolver *Resolver, mapper *ResolverEnhancer) {
    51  	if addr == address && resolver != nil {
    52  		handler := newHandler(resolver, mapper)
    53  		server.setHandler(handler)
    54  		return
    55  	}
    56  
    57  	if server.Server != nil {
    58  		server.Shutdown()
    59  		server = &Server{}
    60  		address = ""
    61  	}
    62  
    63  	if addr == "" {
    64  		return
    65  	}
    66  
    67  	var err error
    68  	defer func() {
    69  		if err != nil {
    70  			log.Errorln("Start DNS server error: %s", err.Error())
    71  		}
    72  	}()
    73  
    74  	_, port, err := net.SplitHostPort(addr)
    75  	if port == "0" || port == "" || err != nil {
    76  		return
    77  	}
    78  
    79  	udpAddr, err := net.ResolveUDPAddr("udp", addr)
    80  	if err != nil {
    81  		return
    82  	}
    83  
    84  	p, err := net.ListenUDP("udp", udpAddr)
    85  	if err != nil {
    86  		return
    87  	}
    88  
    89  	err = sockopt.UDPReuseaddr(p)
    90  	if err != nil {
    91  		log.Warnln("Failed to Reuse UDP Address: %s", err)
    92  
    93  		err = nil
    94  	}
    95  
    96  	address = addr
    97  	handler := newHandler(resolver, mapper)
    98  	server = &Server{handler: handler}
    99  	server.Server = &D.Server{Addr: addr, PacketConn: p, Handler: server}
   100  
   101  	go func() {
   102  		server.ActivateAndServe()
   103  	}()
   104  
   105  	log.Infoln("DNS server listening at: %s", p.LocalAddr().String())
   106  }