diff --git a/client_https.go b/client_https.go new file mode 100644 index 0000000..a7b8775 --- /dev/null +++ b/client_https.go @@ -0,0 +1,59 @@ +package main + +import ( + "bytes" + "context" + "fmt" + "io/ioutil" + "net/http" + "time" + + "github.com/miekg/dns" +) + +type httpclient struct { + Net string + Timeout time.Duration + HTTPClient *http.Client +} + +func (c *httpclient) Exchange(msg *dns.Msg, upstream string) (*dns.Msg, int, error) { + data, err := msg.Pack() + if err != nil { + return nil, 0, err + } + + req, err := http.NewRequest("POST", upstream, bytes.NewReader(data)) + if err != nil { + return nil, 0, err + } + + req.Header.Set("Content-Type", dnsMsgType) + + ctx, cancel := context.WithTimeout(context.Background(), c.Timeout) + defer cancel() + + req = req.WithContext(ctx) + + resp, err := c.HTTPClient.Do(req) + if err != nil { + return nil, 0, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, 0, fmt.Errorf("http error %d", resp.StatusCode) + } + + data, err = ioutil.ReadAll(resp.Body) + if err != nil { + return nil, 0, err + } + + m := new(dns.Msg) + if err = m.Unpack(data); err != nil { + return nil, 0, err + } + + return m, 0, nil +} diff --git a/upstream.go b/upstream.go index 38fa477..3c716dc 100644 --- a/upstream.go +++ b/upstream.go @@ -9,15 +9,15 @@ import ( "net/url" "time" - "github.com/fangdingjun/go-log" + log "github.com/fangdingjun/go-log" "github.com/miekg/dns" "golang.org/x/net/http2" ) var dnsClientTCP *dns.Client -var dnsClientHTTPS *dns.Client var dnsClientUDP *dns.Client var dnsClientTLS *dns.Client +var dnsClientHTTPS *httpclient func getResponseFromUpstream(msg *dns.Msg, upstreams []*url.URL) (*dns.Msg, error) { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) @@ -129,7 +129,7 @@ func initDNSClient(c *conf) { Net: "tcp", Timeout: time.Duration(c.UpstreamTimeout) * time.Second, } - dnsClientHTTPS = &dns.Client{ + dnsClientHTTPS = &httpclient{ Net: "https", Timeout: time.Duration(c.UpstreamTimeout) * time.Second, HTTPClient: &http.Client{