diff --git a/README.md b/README.md index 3880b63..f945500 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,13 @@ # dingo - -A DNS client in Go that supports the [Google +A DNS client (stub resolver) implemented in Go for the [Google DNS-over-HTTPS](https://developers.google.com/speed/public-dns/docs/dns-over-https). It effectively encrypts all your DNS traffic. It also supports [OpenResolve](https://www.openresolve.com/) by OpenDNS. -The ultimate goal for the project is to provide a secure, caching DNS proxy that +The ultimate goal for the project is to provide a secure, caching DNS client that communicates with recursive DNS resolvers over encrypted channels only. For now, -it resolves DNS queries over HTTPS/1.1 in independent threads. The plans for -future include better caching and support for HTTP/2.0 and QUIC. +it resolves DNS queries over HTTP/2 in independent threads. The plans for +future include better caching and support for QUIC. ## Quick start @@ -63,6 +62,8 @@ Usage of dingo-linux-amd64: Google DNS: SNI string to send (should match server certificate) (default "www.google.com") -gdns:workers int Google DNS: number of independent workers (default 10) + -h1 + use HTTPS/1.1 transport -odns:host string OpenDNS: HTTP 'Host' header (real FQDN, encrypted in TLS) (default "api.openresolve.com") -odns:server string diff --git a/dingo.go b/dingo.go index 931cb97..5a37f92 100644 --- a/dingo.go +++ b/dingo.go @@ -23,15 +23,16 @@ import "math/rand" /* command-line arguments */ var ( - bindip = flag.String("bind", "127.0.0.1", "IP address to bind to") - port = flag.Int("port", 32000, "listen on port number") - dbglvl = flag.Int("dbg", 2, "debugging level") + opt_bindip = flag.String("bind", "127.0.0.1", "IP address to bind to") + opt_port = flag.Int("port", 32000, "listen on port number") + opt_h1 = flag.Bool("h1", false, "use HTTPS/1.1 transport") + opt_dbglvl = flag.Int("dbg", 2, "debugging level") ) /**********************************************************************/ /* logging stuff */ -func dbg(lvl int, fmt string, v ...interface{}) { if (*dbglvl >= lvl) { dbglog.Printf(fmt, v...) } } +func dbg(lvl int, fmt string, v ...interface{}) { if (*opt_dbglvl >= lvl) { dbglog.Printf(fmt, v...) } } func die(msg error) { dbglog.Fatalln("fatal error:", msg.Error()) } var dbglog *log.Logger @@ -165,7 +166,7 @@ func main() { rcache = cache.New(24*time.Hour, 60*time.Second) /* listen */ - laddr := net.UDPAddr{ IP: net.ParseIP(*bindip), Port: *port } + laddr := net.UDPAddr{ IP: net.ParseIP(*opt_bindip), Port: *opt_port } uc, err := net.ListenUDP("udp", &laddr) if err != nil { die(err) } @@ -173,7 +174,7 @@ func main() { for _, mod := range Modules { mod.Start() } /* accept new connections forever */ - dbg(1, "dingo ver. 0.12 listening on %s UDP port %d", *bindip, laddr.Port) + dbg(1, "dingo ver. 0.13 listening on %s UDP port %d", *opt_bindip, laddr.Port) var buf []byte for { buf = make([]byte, 1500) diff --git a/gdns.go b/gdns.go index 3a5a8ab..16b8508 100644 --- a/gdns.go +++ b/gdns.go @@ -64,7 +64,9 @@ func (R *Gdns) Start() { func (R *Gdns) worker(server string) { var https = NewHttps(*R.sni) - for q := range qchan { *q.rchan <- *R.resolve(https, server, q.Name, q.Type) } + for q := range qchan { + *q.rchan <- *R.resolve(https, server, q.Name, q.Type) + } } func (R *Gdns) resolve(https *Https, server string, qname string, qtype int) *Reply { diff --git a/https.go b/https.go index 033d9dd..d4122c8 100644 --- a/https.go +++ b/https.go @@ -13,21 +13,34 @@ import "net/http" import "io/ioutil" import "crypto/tls" import "errors" +import "golang.org/x/net/http2" type Https struct { - client http.Client - transport http.Transport - tlscfg tls.Config + client http.Client } func NewHttps(sni string) *Https { H := Https{} - /* basic setup */ + /* TLS setup */ + tlscfg := new(tls.Config) + tlscfg.ServerName = sni + + /* HTTP transport */ + var tr http.RoundTripper + if (*opt_h1) { + h1 := new(http.Transport) + h1.TLSClientConfig = tlscfg + tr = h1 + } else { + h2 := new(http2.Transport) + h2.TLSClientConfig = tlscfg + tr = h2 + } + + /* HTTP client */ H.client.Timeout = time.Second * 10 - H.client.Transport = &H.transport - H.transport.TLSClientConfig = &H.tlscfg - H.tlscfg.ServerName = sni + H.client.Transport = tr return &H }