commit b1bd5dc331f07d95b1cfcb9b3671fa1162fdd3c0 from: Oliver Lowe date: Sun Nov 14 00:31:20 2021 UTC Only forward DNS queries upstream If someone made a POST request with any old bytes in the body we'd forward that upstream regardless. Validate stuff sent to us by parsing the DNS queries and packing, unpacking each, then forward commit - 0a3ca79c8e36dc108fecf910524518063dadd56c commit + b1bd5dc331f07d95b1cfcb9b3671fa1162fdd3c0 blob - b7b3e164f414dddf774a423714f1288467140fd9 blob + cdcde6176c7fc304a0075e0c2f26dbdcaa6355ad --- cmd/dohproxy/dohproxy.go +++ cmd/dohproxy/dohproxy.go @@ -3,35 +3,42 @@ package main import ( "net" "io" - "fmt" "net/http" "log" "git.sr.ht/~otl/dns" -// "golang.org/x/net/dns/dnsmessage" + "golang.org/x/crypto/acme/autocert" + "golang.org/x/net/dns/dnsmessage" ) // https://quad9.net const quad9 string = "9.9.9.9:domain" const cloudflare string = "1.1.1.1:domain" -func forward(msg []byte) ([]byte, error) { - fmt.Println("starting to resolve") +func forward(msg dnsmessage.Message) (dnsmessage.Message, error) { + packed, err := msg.Pack() + if err != nil { + return dnsmessage.Message{}, err + } + conn, err := net.Dial("udp", quad9) if err != nil { - return nil, err + return dnsmessage.Message{}, err } defer conn.Close() - fmt.Println("dialled upstream ok") - if _, err := conn.Write(msg); err != nil { - return nil, err + if _, err := conn.Write(packed); err != nil { + return dnsmessage.Message{}, err } - fmt.Println("wrote request to upstream ok") buf := make([]byte, 1024) n, err := conn.Read(buf) if err != nil { - return nil, err + return dnsmessage.Message{}, err } - return buf[:n], nil + + var rmsg dnsmessage.Message + if err := rmsg.Unpack(buf[:n]); err != nil { + return dnsmessage.Message{}, err + } + return rmsg, nil } func dnsHandler(w http.ResponseWriter, req *http.Request) { @@ -52,13 +59,11 @@ func dnsHandler(w http.ResponseWriter, req *http.Reque buf := make([]byte, 512) switch req.Method { case http.MethodPost: - fmt.Println("got a POST request") _, err := req.Body.Read(buf) if err != nil && err != io.EOF { http.Error(w, err.Error(), http.StatusInternalServerError) return } - fmt.Println("read request body into buffer") req.Body.Close() case http.MethodGet: log.Println("got a GET request but that's not implemented") @@ -66,19 +71,30 @@ func dnsHandler(w http.ResponseWriter, req *http.Reque return } - resolved, err := forward(buf) + var msg dnsmessage.Message + if err := msg.Unpack(buf); err != nil { + log.Println("unpack query:", err) + http.Error(w, "unpack query: "+err.Error(), http.StatusInternalServerError) + } + + resolved, err := forward(msg) if err != nil { - fmt.Println(err.Error()) + log.Println(err.Error()) http.Error(w, err.Error(), http.StatusInternalServerError) return } + packed, err := resolved.Pack() + if err != nil { + log.Println("pack resolved query:", err.Error) + http.Error(w, err.Error(), http.StatusInternalServerError) + } w.Header().Add("Content-Type", dns.MediaType) - if _, err := w.Write(resolved); err != nil { + if _, err := w.Write(packed); err != nil { log.Fatalln(err) } } func main() { http.HandleFunc("/dns-query", dnsHandler) - log.Fatalln(http.ListenAndServeTLS("127.0.0.1:8080", "otl.crt", "otl.key", nil)) + log.Fatalln(http.Serve(autocert.NewListener("syd.olowe.co"), nil)) } blob - 537ad850f1450847cc55b1be86e424d631cd4241 blob + da468ca44cc7be238bbfdf9b228b4be2b8db9e3b --- go.mod +++ go.mod @@ -1,3 +1,9 @@ module git.sr.ht/~otl/dns go 1.17 + +require ( + golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa // indirect + golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect + golang.org/x/text v0.3.3 // indirect +) blob - e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 blob + 64a51352e01b4bfa8f3b38c539eeac8143307c91 --- go.sum +++ go.sum @@ -0,0 +1,9 @@ +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa h1:idItI2DDfCokpg0N51B2VtiLdJ4vAuXC9fnCb2gACo4= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=