github.com/kelleygo/clashcore@v1.0.2/hub/route/dns.go (about) 1 package route 2 3 import ( 4 "context" 5 "math" 6 "net/http" 7 8 "github.com/kelleygo/clashcore/component/resolver" 9 10 "github.com/go-chi/chi/v5" 11 "github.com/go-chi/render" 12 "github.com/miekg/dns" 13 "github.com/samber/lo" 14 ) 15 16 func dnsRouter() http.Handler { 17 r := chi.NewRouter() 18 r.Get("/query", queryDNS) 19 return r 20 } 21 22 func queryDNS(w http.ResponseWriter, r *http.Request) { 23 if resolver.DefaultResolver == nil { 24 render.Status(r, http.StatusInternalServerError) 25 render.JSON(w, r, newError("DNS section is disabled")) 26 return 27 } 28 29 name := r.URL.Query().Get("name") 30 qTypeStr, _ := lo.Coalesce(r.URL.Query().Get("type"), "A") 31 32 qType, exist := dns.StringToType[qTypeStr] 33 if !exist { 34 render.Status(r, http.StatusBadRequest) 35 render.JSON(w, r, newError("invalid query type")) 36 return 37 } 38 39 ctx, cancel := context.WithTimeout(context.Background(), resolver.DefaultDNSTimeout) 40 defer cancel() 41 42 msg := dns.Msg{} 43 msg.SetQuestion(dns.Fqdn(name), qType) 44 resp, err := resolver.DefaultResolver.ExchangeContext(ctx, &msg) 45 if err != nil { 46 render.Status(r, http.StatusInternalServerError) 47 render.JSON(w, r, newError(err.Error())) 48 return 49 } 50 51 responseData := render.M{ 52 "Status": resp.Rcode, 53 "Question": resp.Question, 54 "TC": resp.Truncated, 55 "RD": resp.RecursionDesired, 56 "RA": resp.RecursionAvailable, 57 "AD": resp.AuthenticatedData, 58 "CD": resp.CheckingDisabled, 59 } 60 61 rr2Json := func(rr dns.RR, _ int) render.M { 62 header := rr.Header() 63 return render.M{ 64 "name": header.Name, 65 "type": header.Rrtype, 66 "TTL": header.Ttl, 67 "data": lo.Substring(rr.String(), len(header.String()), math.MaxUint), 68 } 69 } 70 71 if len(resp.Answer) > 0 { 72 responseData["Answer"] = lo.Map(resp.Answer, rr2Json) 73 } 74 if len(resp.Ns) > 0 { 75 responseData["Authority"] = lo.Map(resp.Ns, rr2Json) 76 } 77 if len(resp.Extra) > 0 { 78 responseData["Additional"] = lo.Map(resp.Extra, rr2Json) 79 } 80 81 render.JSON(w, r, responseData) 82 }