commit - 0500699332efdcf7796b1879af478f78f096d221
commit + 1bcf9fa40865b1840d67029d990dcbfe61a43a23
blob - 9f9e7c4fce25cec9470d84094173f1178fd40728
blob + 47ba0dc39d58efbdec7c563c02c362ae15bd4a4a
--- cmd/dohproxy/dohproxy.go
+++ cmd/dohproxy/dohproxy.go
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 {
err := fmt.Errorf("unsupported media type %s", s)
log.Println(err.Error())
http.Error(w, err.Error(), http.StatusUnsupportedMediaType)
- return
+ return
}
}
}
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
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
+}