Skip to content

Commit

Permalink
Feature: add dns query json api
Browse files Browse the repository at this point in the history
  • Loading branch information
Dreamacro authored and stitchrs committed Jan 27, 2023
1 parent 85db58a commit a6a72a5
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 13 deletions.
3 changes: 3 additions & 0 deletions component/resolver/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"time"

"github.com/Dreamacro/clash/component/trie"

"github.com/miekg/dns"
)

var (
Expand Down Expand Up @@ -44,6 +46,7 @@ type Resolver interface {
ResolveIP(ctx context.Context, host string) (ip netip.Addr, err error)
ResolveIPv4(ctx context.Context, host string) (ip netip.Addr, err error)
ResolveIPv6(ctx context.Context, host string) (ip netip.Addr, err error)
ExchangeContext(ctx context.Context, m *dns.Msg) (msg *dns.Msg, err error)
}

// LookupIPv4WithResolver same as LookupIPv4, but with a resolver
Expand Down
13 changes: 5 additions & 8 deletions hub/route/configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ func pointerOrDefault(p *int, def int) int {
if p != nil {
return *p
}

return def
}

Expand Down Expand Up @@ -210,7 +209,7 @@ func pointerOrDefaultTuicServer(p *tuicServerSchema, def LC.TuicServer) LC.TuicS

func patchConfigs(w http.ResponseWriter, r *http.Request) {
general := &configSchema{}
if err := render.DecodeJSON(r.Body, general); err != nil {
if err := render.DecodeJSON(r.Body, &general); err != nil {
render.Status(r, http.StatusBadRequest)
render.JSON(w, r, ErrBadRequest)
return
Expand Down Expand Up @@ -266,13 +265,11 @@ func patchConfigs(w http.ResponseWriter, r *http.Request) {
render.NoContent(w, r)
}

type updateConfigRequest struct {
Path string `json:"path"`
Payload string `json:"payload"`
}

func updateConfigs(w http.ResponseWriter, r *http.Request) {
req := updateConfigRequest{}
req := struct {
Path string `json:"path"`
Payload string `json:"payload"`
}{}
if err := render.DecodeJSON(r.Body, &req); err != nil {
render.Status(r, http.StatusBadRequest)
render.JSON(w, r, ErrBadRequest)
Expand Down
76 changes: 76 additions & 0 deletions hub/route/dns.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package route

import (
"context"
"math"
"net/http"

"github.com/Dreamacro/clash/component/resolver"

"github.com/go-chi/chi/v5"
"github.com/go-chi/render"
"github.com/miekg/dns"
"github.com/samber/lo"
)

func dnsRouter() http.Handler {
r := chi.NewRouter()
r.Get("/query", queryDNS)
return r
}

func queryDNS(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
qTypeStr, _ := lo.Coalesce(r.URL.Query().Get("type"), "A")

qType, exist := dns.StringToType[qTypeStr]
if !exist {
render.Status(r, http.StatusBadRequest)
render.JSON(w, r, newError("invalid query type"))
return
}

ctx, cancel := context.WithTimeout(context.Background(), resolver.DefaultDNSTimeout)
defer cancel()

msg := dns.Msg{}
msg.SetQuestion(dns.Fqdn(name), qType)
resp, err := resolver.DefaultResolver.ExchangeContext(ctx, &msg)
if err != nil {
render.Status(r, http.StatusInternalServerError)
render.JSON(w, r, newError(err.Error()))
return
}

responseData := render.M{
"Status": resp.Rcode,
"Question": resp.Question,
"TC": resp.Truncated,
"RD": resp.RecursionDesired,
"RA": resp.RecursionAvailable,
"AD": resp.AuthenticatedData,
"CD": resp.CheckingDisabled,
}

rr2Json := func(rr dns.RR, _ int) render.M {
header := rr.Header()
return render.M{
"name": header.Name,
"type": header.Rrtype,
"TTL": header.Ttl,
"data": lo.Substring(rr.String(), len(header.String()), math.MaxUint),
}
}

if len(resp.Answer) > 0 {
responseData["Answer"] = lo.Map(resp.Answer, rr2Json)
}
if len(resp.Ns) > 0 {
responseData["Authority"] = lo.Map(resp.Ns, rr2Json)
}
if len(resp.Extra) > 0 {
responseData["Additional"] = lo.Map(resp.Extra, rr2Json)
}

render.JSON(w, r, responseData)
}
8 changes: 3 additions & 5 deletions hub/route/proxies.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,10 @@ func getProxy(w http.ResponseWriter, r *http.Request) {
render.JSON(w, r, proxy)
}

type UpdateProxyRequest struct {
Name string `json:"name"`
}

func updateProxy(w http.ResponseWriter, r *http.Request) {
req := UpdateProxyRequest{}
req := struct {
Name string `json:"name"`
}{}
if err := render.DecodeJSON(r.Body, &req); err != nil {
render.Status(r, http.StatusBadRequest)
render.JSON(w, r, ErrBadRequest)
Expand Down
1 change: 1 addition & 0 deletions hub/route/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ func Start(addr string, tlsAddr string, secret string,
r.Mount("/providers/proxies", proxyProviderRouter())
r.Mount("/providers/rules", ruleProviderRouter())
r.Mount("/cache", cacheRouter())
r.Mount("/dns", dnsRouter())
})

if uiPath != "" {
Expand Down

0 comments on commit a6a72a5

Please sign in to comment.