Commit Diff


commit - 0500699332efdcf7796b1879af478f78f096d221
commit + 1bcf9fa40865b1840d67029d990dcbfe61a43a23
blob - 9f9e7c4fce25cec9470d84094173f1178fd40728
blob + 47ba0dc39d58efbdec7c563c02c362ae15bd4a4a
--- cmd/dohproxy/dohproxy.go
+++ cmd/dohproxy/dohproxy.go
@@ -1,48 +1,21 @@
 package main
 
 import (
-	"net"
+	"fmt"
+	"golang.org/x/crypto/acme/autocert"
+	"golang.org/x/net/dns/dnsmessage"
 	"io"
-	"net/http"
 	"log"
-	"fmt"
+	"net/http"
 	"strconv"
+
 	"git.sr.ht/~otl/dns"
-	"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 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 dnsmessage.Message{}, err
-	}
-	defer conn.Close()
-	if _, err := conn.Write(packed); err != nil {
-		return dnsmessage.Message{}, err
-	}
-	buf := make([]byte, 1024)
-	n, err := conn.Read(buf)
-	if err != nil {
-		return dnsmessage.Message{}, err
-	}
-
-	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) {
 	if v, ok := req.Header["Content-Type"]; ok {
 		for _, s := range v {
@@ -50,7 +23,7 @@ func dnsHandler(w http.ResponseWriter, req *http.Reque
 				err := fmt.Errorf("unsupported media type %s", s)
 				log.Println(err.Error())
 				http.Error(w, err.Error(), http.StatusUnsupportedMediaType)
-				 return
+				return
 			}
 		}
 	}
@@ -101,7 +74,7 @@ func dnsHandler(w http.ResponseWriter, req *http.Reque
 		http.Error(w, "unpack query: "+err.Error(), http.StatusInternalServerError)
 	}
 
-	resolved, err := forward(msg)
+	resolved, err := dns.Exchange(msg, quad9)
 	if err != nil {
 		log.Println(err.Error())
 		http.Error(w, err.Error(), http.StatusInternalServerError)
blob - 9fccf8580adac92df56a618dc946d7db40322e52
blob + 0c66051917400b8253ab00299af5f82fa2c73de1
--- dns.go
+++ dns.go
@@ -1,5 +1,42 @@
 package dns
 
+import (
+	"net"
+
+	"golang.org/x/net/dns/dnsmessage"
+)
+
 // https://datatracker.ietf.org/doc/html/rfc8484
 const MediaType string = "application/dns-message"
 const MaxMsgSize int = 65535 // max size of a message in bytes
+
+// Exchange performs a synchronous, unencrypted UDP DNS exchange with addr and returns its
+// reply to msg.
+func Exchange(msg dnsmessage.Message, addr string) (dnsmessage.Message, error) {
+	conn, err := net.Dial("udp", addr)
+	if err != nil {
+		return dnsmessage.Message{}, err
+	}
+	defer conn.Close()
+	return send(msg, conn)
+}
+
+func send(msg dnsmessage.Message, conn net.Conn) (dnsmessage.Message, error) {
+	packed, err := msg.Pack()
+	if err != nil {
+		return dnsmessage.Message{}, err
+	}
+	if _, err := conn.Write(packed); err != nil {
+		return dnsmessage.Message{}, err
+	}
+	buf := make([]byte, 1024)
+	n, err := conn.Read(buf)
+	if err != nil {
+		return dnsmessage.Message{}, err
+	}
+	var rmsg dnsmessage.Message
+	if err := rmsg.Unpack(buf[:n]); err != nil {
+		return dnsmessage.Message{}, err
+	}
+	return rmsg, nil
+}