commit 0a3ca79c8e36dc108fecf910524518063dadd56c from: Oliver Lowe date: Sat Nov 13 03:04:50 2021 UTC Make git.sr.ht/~otl/dns a Go package And rename dohtest to dohproxy. This thing is going live soon baby commit - 8286582481dcaeaca322a57edebda5a492cf9b98 commit + 0a3ca79c8e36dc108fecf910524518063dadd56c blob - 5f7afb37fd3e9be64f6cc8b80f72cf7d09ceff18 blob + 1eb11d5777f06ecc8a324d0de1c0172428f45467 --- README +++ 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 blob - /dev/null blob + 512efab720dac8620b61fe8f9e95bb104a1ce5ab (mode 644) --- /dev/null +++ .gitignore @@ -0,0 +1 @@ +cmd/dohproxy/dohproxy blob - 850e688e1dc20a08d62ec4a07b53fd28f31ac176 (mode 644) blob + /dev/null --- dohtest.go +++ /dev/null @@ -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)) -} blob - 82041035bdaa647eccb52c5a29178e2dc6db722c blob + 537ad850f1450847cc55b1be86e424d631cd4241 --- go.mod +++ go.mod @@ -1,3 +1,3 @@ -module dohtest +module git.sr.ht/~otl/dns go 1.17 blob - /dev/null blob + b7b3e164f414dddf774a423714f1288467140fd9 (mode 644) --- /dev/null +++ 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)) +} blob - /dev/null blob + c3368d780dd186c8b64cc763e7ba8f9e0d7a08d4 (mode 644) --- /dev/null +++ cmd/dohproxy/otl.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDETCCAfkCFADa656sE6T5zS9oDaC1mfiWGR6lMA0GCSqGSIb3DQEBCwUAMEUx +CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl +cm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMjExMTEwMDUzMzQ2WhcNMjIxMTEwMDUz +MzQ2WjBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UE +CgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA4AKxdfnyoC/I1uCQX39n3Rr6jLcSdA3DfHliLyGqBPqPdY+K +msJx76FJrsNOr+wPQ3dY9ERr4YybAXIWmnlmg5dCWH3UIlc6aJ4xpJeegVpyizZV +kPP9vxE+zWOYNGxBBTAI8makzattWu1DSRwJtYnhDCdYI5TjsSVEH3Z2+i2IWxLL ++h03ctlQxnp0ETBrKL6X8HvWp5ZaxpUWDYF3CXwvp4W4Eg3QuzgGWsyj9DyiesQu +MQCZWFxfzChXwmk9skDjYS7s8pszjBUms0GDOhZ5+ja6o/NkNmEXmOmNad3QfXzb +46PeKgkNwt/Ty43qXbCg+9mf9zH+Joqd36WoYwIDAQABMA0GCSqGSIb3DQEBCwUA +A4IBAQA+cWln5Xg2T8Az/J7afv2rQBRrrRq/N3/77C0+e55Cvoo2Ogp1SVMpVNEd +02VPndB+24hbEqAbg5Sx9xJCxn8EaRgdLnX+T4+U19WxD72szoxz2m2Y4AgDdODj +W5lmL854z/Gc9XBrrIHV6CFfm30S+o2wzj8EjoDWiySCwi34FVqjBgMYa3Fk/f5a +Nfa8CsYS8ZyYa8cApAAsjjHC6kW5/9mGogoQ9S2+AwqxmqTrzb0NkmlOnOs5Lf+X +M5DMzva2DBrw6r4kEBQEdnTKLXvzf5je/V5YEhS3zE0VNS5MxxVF+B/eXf1/Itn9 +hIBulmvNVFiF+bJ6V5AO1zNZs/gQ +-----END CERTIFICATE----- blob - /dev/null blob + 147a8c2072100da6de49803e40ee18e204973268 (mode 644) --- /dev/null +++ cmd/dohproxy/otl.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA4AKxdfnyoC/I1uCQX39n3Rr6jLcSdA3DfHliLyGqBPqPdY+K +msJx76FJrsNOr+wPQ3dY9ERr4YybAXIWmnlmg5dCWH3UIlc6aJ4xpJeegVpyizZV +kPP9vxE+zWOYNGxBBTAI8makzattWu1DSRwJtYnhDCdYI5TjsSVEH3Z2+i2IWxLL ++h03ctlQxnp0ETBrKL6X8HvWp5ZaxpUWDYF3CXwvp4W4Eg3QuzgGWsyj9DyiesQu +MQCZWFxfzChXwmk9skDjYS7s8pszjBUms0GDOhZ5+ja6o/NkNmEXmOmNad3QfXzb +46PeKgkNwt/Ty43qXbCg+9mf9zH+Joqd36WoYwIDAQABAoIBAE4cIk0E7rk0cE+c +1jq2bj0G3z6Zx3F4KyYIHVhZ4LMDu2o+txHno1rvXoX1zEZDhb78qqPiB8wJ/zKt +2XvbwQc5gwTgO0wOJmu8XYsK41Yvd6lbNNLqgRxSoxdzFuuQo8tvSG9dozGkCOmf +ucqQYEJQ5YwbW/xsOkjWub5OzIXHG6/74g6c7VPTr5PqjdGOwgsbDcWEQrwlU7po +XhZbKUIfmmPDKUxv5hd+xHnlke+O2+P15Z5pLrT1XBzoICdsmJORG1tq649YVCa7 +0OzhSJmwFKrTF781z87k9Rk/3axbEZ84VWSKBGMzwDzIL3uKjw7QmKF8lzClwFWe +RyMEPAECgYEA9AhJl08hF4xUKIDCwChjMBbEHPAGHyToYzMaLfAKxXM7uCB4WtEP +AQ72bK6sF0hI0b3ILGLgWds4PncRpRa9GA1ISdIUPF+9HOtiWvAIaYsJ0EcRDhZo +an7rcb+QxsQe4AY1q+e/gTENhjdxzLUTf6aLGznQOt/TZVwqw+dgQeMCgYEA6v8K +bSU89yjfXd6haahnM+E2eKpP5PF+g764g9gsW6vuJSEAlN4hgr2iCCql3IK33Zyo +A+hl6kfn8DH0c35Q9WHTpMFx/cGPljZoxgTjz2ZzEoXYy8J9rYgWM9PTB6oViPlL +hvNXBZRK8HBnknNByuhDJe5AJS2hLHJiCebvx4ECgYAnsI1fiaQlM1Kgv8hs/mSb +dqhw2Gz2dcdCExan8AmgcYx99vH8O1JIZsmXhZVBuCT3z/kVlwNMOgZcynrZMeiR +V9+w+fUGmL+mS3ZUugN0PwPalyRj+SsEXx4mAvUmDtHCt9/U1L1l4reDY9MjazP/ +p/Op+u4uFSdJrgLal/Ak5wKBgQCsETEeOB0K0Ne1ERXZmqBuoWJUOkij15wOdXD/ +wSLBwQNwFlkpp/iblaT2G9w0uVZOI632po0xXZNcEgfvJTe8ZPQmeCqyZq9vislu +7RetvlNV5cGXeQKzNKklK94ih4ybLgb6emVmxW2V3ohH+LLdEvJP7ML1NhMEy4Az +xfAegQKBgQCxyi6BaA1aXzl+CiBqn80E8BR997ykOTFoHPM+JRiTaHgaNXN7Na8h +NMhI6yN3VAszdIbiefoKUJEkw/nLLWn0NyklXin/XZjvKKL/5rrtilqDhmGheRXm +QbMMbSHDNsX38G4v+c66iyJrTKEMMPo0qDYw3VHCRPH/vuGCy66Gvw== +-----END RSA PRIVATE KEY----- blob - /dev/null blob + 9fccf8580adac92df56a618dc946d7db40322e52 (mode 644) --- /dev/null +++ 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 blob - c3368d780dd186c8b64cc763e7ba8f9e0d7a08d4 (mode 644) blob + /dev/null --- otl.crt +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDETCCAfkCFADa656sE6T5zS9oDaC1mfiWGR6lMA0GCSqGSIb3DQEBCwUAMEUx -CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl -cm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMjExMTEwMDUzMzQ2WhcNMjIxMTEwMDUz -MzQ2WjBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UE -CgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEA4AKxdfnyoC/I1uCQX39n3Rr6jLcSdA3DfHliLyGqBPqPdY+K -msJx76FJrsNOr+wPQ3dY9ERr4YybAXIWmnlmg5dCWH3UIlc6aJ4xpJeegVpyizZV -kPP9vxE+zWOYNGxBBTAI8makzattWu1DSRwJtYnhDCdYI5TjsSVEH3Z2+i2IWxLL -+h03ctlQxnp0ETBrKL6X8HvWp5ZaxpUWDYF3CXwvp4W4Eg3QuzgGWsyj9DyiesQu -MQCZWFxfzChXwmk9skDjYS7s8pszjBUms0GDOhZ5+ja6o/NkNmEXmOmNad3QfXzb -46PeKgkNwt/Ty43qXbCg+9mf9zH+Joqd36WoYwIDAQABMA0GCSqGSIb3DQEBCwUA -A4IBAQA+cWln5Xg2T8Az/J7afv2rQBRrrRq/N3/77C0+e55Cvoo2Ogp1SVMpVNEd -02VPndB+24hbEqAbg5Sx9xJCxn8EaRgdLnX+T4+U19WxD72szoxz2m2Y4AgDdODj -W5lmL854z/Gc9XBrrIHV6CFfm30S+o2wzj8EjoDWiySCwi34FVqjBgMYa3Fk/f5a -Nfa8CsYS8ZyYa8cApAAsjjHC6kW5/9mGogoQ9S2+AwqxmqTrzb0NkmlOnOs5Lf+X -M5DMzva2DBrw6r4kEBQEdnTKLXvzf5je/V5YEhS3zE0VNS5MxxVF+B/eXf1/Itn9 -hIBulmvNVFiF+bJ6V5AO1zNZs/gQ ------END CERTIFICATE----- blob - 147a8c2072100da6de49803e40ee18e204973268 (mode 644) blob + /dev/null --- otl.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEA4AKxdfnyoC/I1uCQX39n3Rr6jLcSdA3DfHliLyGqBPqPdY+K -msJx76FJrsNOr+wPQ3dY9ERr4YybAXIWmnlmg5dCWH3UIlc6aJ4xpJeegVpyizZV -kPP9vxE+zWOYNGxBBTAI8makzattWu1DSRwJtYnhDCdYI5TjsSVEH3Z2+i2IWxLL -+h03ctlQxnp0ETBrKL6X8HvWp5ZaxpUWDYF3CXwvp4W4Eg3QuzgGWsyj9DyiesQu -MQCZWFxfzChXwmk9skDjYS7s8pszjBUms0GDOhZ5+ja6o/NkNmEXmOmNad3QfXzb -46PeKgkNwt/Ty43qXbCg+9mf9zH+Joqd36WoYwIDAQABAoIBAE4cIk0E7rk0cE+c -1jq2bj0G3z6Zx3F4KyYIHVhZ4LMDu2o+txHno1rvXoX1zEZDhb78qqPiB8wJ/zKt -2XvbwQc5gwTgO0wOJmu8XYsK41Yvd6lbNNLqgRxSoxdzFuuQo8tvSG9dozGkCOmf -ucqQYEJQ5YwbW/xsOkjWub5OzIXHG6/74g6c7VPTr5PqjdGOwgsbDcWEQrwlU7po -XhZbKUIfmmPDKUxv5hd+xHnlke+O2+P15Z5pLrT1XBzoICdsmJORG1tq649YVCa7 -0OzhSJmwFKrTF781z87k9Rk/3axbEZ84VWSKBGMzwDzIL3uKjw7QmKF8lzClwFWe -RyMEPAECgYEA9AhJl08hF4xUKIDCwChjMBbEHPAGHyToYzMaLfAKxXM7uCB4WtEP -AQ72bK6sF0hI0b3ILGLgWds4PncRpRa9GA1ISdIUPF+9HOtiWvAIaYsJ0EcRDhZo -an7rcb+QxsQe4AY1q+e/gTENhjdxzLUTf6aLGznQOt/TZVwqw+dgQeMCgYEA6v8K -bSU89yjfXd6haahnM+E2eKpP5PF+g764g9gsW6vuJSEAlN4hgr2iCCql3IK33Zyo -A+hl6kfn8DH0c35Q9WHTpMFx/cGPljZoxgTjz2ZzEoXYy8J9rYgWM9PTB6oViPlL -hvNXBZRK8HBnknNByuhDJe5AJS2hLHJiCebvx4ECgYAnsI1fiaQlM1Kgv8hs/mSb -dqhw2Gz2dcdCExan8AmgcYx99vH8O1JIZsmXhZVBuCT3z/kVlwNMOgZcynrZMeiR -V9+w+fUGmL+mS3ZUugN0PwPalyRj+SsEXx4mAvUmDtHCt9/U1L1l4reDY9MjazP/ -p/Op+u4uFSdJrgLal/Ak5wKBgQCsETEeOB0K0Ne1ERXZmqBuoWJUOkij15wOdXD/ -wSLBwQNwFlkpp/iblaT2G9w0uVZOI632po0xXZNcEgfvJTe8ZPQmeCqyZq9vislu -7RetvlNV5cGXeQKzNKklK94ih4ybLgb6emVmxW2V3ohH+LLdEvJP7ML1NhMEy4Az -xfAegQKBgQCxyi6BaA1aXzl+CiBqn80E8BR997ykOTFoHPM+JRiTaHgaNXN7Na8h -NMhI6yN3VAszdIbiefoKUJEkw/nLLWn0NyklXin/XZjvKKL/5rrtilqDhmGheRXm -QbMMbSHDNsX38G4v+c66iyJrTKEMMPo0qDYw3VHCRPH/vuGCy66Gvw== ------END RSA PRIVATE KEY-----