github.com/metacubex/mihomo@v1.18.5/dns/server.go (about)

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