2018-05-21 19:40:46 +01:00
|
|
|
package dnsserver
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"encoding/base64"
|
|
|
|
|
"fmt"
|
|
|
|
|
"io/ioutil"
|
2018-05-23 13:50:27 +01:00
|
|
|
"net"
|
2018-05-21 19:40:46 +01:00
|
|
|
"net/http"
|
|
|
|
|
|
2018-05-23 13:50:27 +01:00
|
|
|
"github.com/coredns/coredns/plugin/pkg/nonwriter"
|
2018-05-21 19:40:46 +01:00
|
|
|
"github.com/miekg/dns"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// mimeTypeDOH is the DoH mimetype that should be used.
|
|
|
|
|
const mimeTypeDOH = "application/dns-message"
|
|
|
|
|
|
|
|
|
|
// pathDOH is the URL path that should be used.
|
|
|
|
|
const pathDOH = "/dns-query"
|
|
|
|
|
|
|
|
|
|
// postRequestToMsg extracts the dns message from the request body.
|
|
|
|
|
func postRequestToMsg(req *http.Request) (*dns.Msg, error) {
|
|
|
|
|
defer req.Body.Close()
|
|
|
|
|
|
|
|
|
|
buf, err := ioutil.ReadAll(req.Body)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
m := new(dns.Msg)
|
|
|
|
|
err = m.Unpack(buf)
|
|
|
|
|
return m, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// getRequestToMsg extract the dns message from the GET request.
|
|
|
|
|
func getRequestToMsg(req *http.Request) (*dns.Msg, error) {
|
|
|
|
|
values := req.URL.Query()
|
|
|
|
|
b64, ok := values["dns"]
|
|
|
|
|
if !ok {
|
|
|
|
|
return nil, fmt.Errorf("no 'dns' query parameter found")
|
|
|
|
|
}
|
|
|
|
|
if len(b64) != 1 {
|
|
|
|
|
return nil, fmt.Errorf("multiple 'dns' query values found")
|
|
|
|
|
}
|
|
|
|
|
return base64ToMsg(b64[0])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func base64ToMsg(b64 string) (*dns.Msg, error) {
|
|
|
|
|
buf, err := b64Enc.DecodeString(b64)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m := new(dns.Msg)
|
|
|
|
|
err = m.Unpack(buf)
|
|
|
|
|
|
|
|
|
|
return m, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var b64Enc = base64.RawURLEncoding
|
2018-05-23 13:50:27 +01:00
|
|
|
|
|
|
|
|
// DoHWriter is a nonwriter.Writer that adds more specific LocalAddr and RemoteAddr methods.
|
|
|
|
|
type DoHWriter struct {
|
|
|
|
|
nonwriter.Writer
|
|
|
|
|
|
|
|
|
|
// raddr is the remote's address. This can be optionally set.
|
|
|
|
|
raddr net.Addr
|
|
|
|
|
// laddr is our address. This can be optionally set.
|
|
|
|
|
laddr net.Addr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// RemoteAddr returns the remote address.
|
|
|
|
|
func (d *DoHWriter) RemoteAddr() net.Addr { return d.raddr }
|
|
|
|
|
|
|
|
|
|
// LocalAddr returns the local address.
|
|
|
|
|
func (d *DoHWriter) LocalAddr() net.Addr { return d.laddr }
|