dns

DNS client and server implementations using the Go project's dnsmessage package
Log | Files | Refs | README | LICENSE

commit 0a3ca79c8e36dc108fecf910524518063dadd56c
parent 8286582481dcaeaca322a57edebda5a492cf9b98
Author: Oliver Lowe <o@olowe.co>
Date:   Sat, 13 Nov 2021 14:03:31 +1100

Make git.sr.ht/~otl/dns a Go package

And rename dohtest to dohproxy. This thing is going live soon baby

Diffstat:
A.gitignore | 1+
MREADME | 6+++++-
Acmd/dohproxy/dohproxy.go | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rotl.crt -> cmd/dohproxy/otl.crt | 0
Rotl.key -> cmd/dohproxy/otl.key | 0
Adns.go | 5+++++
Ddohtest.go | 82-------------------------------------------------------------------------------
Mgo.mod | 2+-
8 files changed, 96 insertions(+), 84 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1 @@ +cmd/dohproxy/dohproxy diff --git a/README b/README @@ -1,7 +1,11 @@ Please don't use this yet + $ cd cmd/dohproxy $ go build - $ ./dohtest $ curl -v --doh-insecure --doh-url https://127.0.0.1:8080/dns-query http://www.olowe.co Adjust upstream resolver by changing `quad9` to some other address. + +https://blog.nlnetlabs.nl/dns-over-https-in-unbound/ + +https://datatracker.ietf.org/doc/html/rfc8484 diff --git a/cmd/dohproxy/dohproxy.go b/cmd/dohproxy/dohproxy.go @@ -0,0 +1,84 @@ +package main + +import ( + "net" + "io" + "fmt" + "net/http" + "log" + "git.sr.ht/~otl/dns" +// "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") + conn, err := net.Dial("udp", quad9) + if err != nil { + return nil, err + } + defer conn.Close() + fmt.Println("dialled upstream ok") + if _, err := conn.Write(msg); err != nil { + return nil, err + } + fmt.Println("wrote request to upstream ok") + buf := make([]byte, 1024) + n, err := conn.Read(buf) + if err != nil { + return nil, err + } + return buf[:n], nil +} + +func dnsHandler(w http.ResponseWriter, req *http.Request) { + if v, ok := req.Header["Content-Type"]; ok { + for _, s := range v { + if s != dns.MediaType { + http.Error(w, "unsupported media type", http.StatusUnsupportedMediaType) + return + } + } + } + + if req.Method != http.MethodPost && req.Method != http.MethodGet { + http.Error(w, "method must be GET or POST", http.StatusNotImplemented) + return + } + + 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") + http.Error(w, "in progress!", http.StatusNotImplemented) + return + } + + resolved, err := forward(buf) + if err != nil { + fmt.Println(err.Error()) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + w.Header().Add("Content-Type", dns.MediaType) + if _, err := w.Write(resolved); 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)) +} diff --git a/otl.crt b/cmd/dohproxy/otl.crt diff --git a/otl.key b/cmd/dohproxy/otl.key diff --git a/dns.go b/dns.go @@ -0,0 +1,5 @@ +package dns + +// https://datatracker.ietf.org/doc/html/rfc8484 +const MediaType string = "application/dns-message" +const MaxMsgSize int = 65535 // max size of a message in bytes diff --git a/dohtest.go b/dohtest.go @@ -1,82 +0,0 @@ -package main - -import ( - "net" - "io" - "fmt" - "net/http" - "log" -// "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" -const dnsMediaType string = "application/dns-message" - -func forward(msg []byte) ([]byte, error) { - fmt.Println("starting to resolve") - conn, err := net.Dial("udp", cloudflare) - if err != nil { - return nil, err - } - defer conn.Close() - fmt.Println("dialled upstream ok") - if _, err := conn.Write(msg); err != nil { - return nil, err - } - fmt.Println("wrote request to upstream ok") - buf := make([]byte, 1024) - n, err := conn.Read(buf) - if err != nil { - return nil, err - } - return buf[:n], nil -} - -func dnsHandler(w http.ResponseWriter, req *http.Request) { - if v, ok := req.Header["Content-Type"]; ok { - for _, s := range v { - if s != dnsMediaType { - http.Error(w, "unsupported media type", http.StatusUnsupportedMediaType) - return - } - } - } - - 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") - http.Error(w, "in progress!", http.StatusNotImplemented) - return - default: - http.Error(w, "method must be GET or POST", http.StatusNotImplemented) - return - } - - resolved, err := forward(buf) - if err != nil { - fmt.Println(err.Error()) - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - w.Header().Add("Content-type", dnsMediaType) - if _, err := w.Write(resolved); 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)) -} diff --git a/go.mod b/go.mod @@ -1,3 +1,3 @@ -module dohtest +module git.sr.ht/~otl/dns go 1.17