commit - 8286582481dcaeaca322a57edebda5a492cf9b98
commit + 0a3ca79c8e36dc108fecf910524518063dadd56c
blob - 5f7afb37fd3e9be64f6cc8b80f72cf7d09ceff18
blob + 1eb11d5777f06ecc8a324d0de1c0172428f45467
--- README
+++ README
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
+cmd/dohproxy/dohproxy
blob - 850e688e1dc20a08d62ec4a07b53fd28f31ac176 (mode 644)
blob + /dev/null
--- dohtest.go
+++ /dev/null
-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
-module dohtest
+module git.sr.ht/~otl/dns
go 1.17
blob - /dev/null
blob + b7b3e164f414dddf774a423714f1288467140fd9 (mode 644)
--- /dev/null
+++ cmd/dohproxy/dohproxy.go
+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
+-----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
+-----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
+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
------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
------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-----