diff --git a/Readme.md b/Readme.md index a006b28..45d45a7 100644 --- a/Readme.md +++ b/Readme.md @@ -11,8 +11,8 @@ and [IETF DNS-over-HTTPS (RFC 8484)](https://www.rfc-editor.org/rfc/rfc8484.txt) ## Installing ### From Source -- Install [Go](https://golang.org), at least version 1.13. The newer the better. -> Note for Debian/Ubuntu users: You need to set `$GOROOT` if you could not get your new version of Go selected by the Makefile.) +- Install [Go](https://golang.org), at least version 1.13. The newer, the better. +> Note for Debian/Ubuntu users: You need to set `$GOROOT` if you could not get your new version of Go selected by the Makefile. - First create an empty directory, used for `$GOPATH`: ```bash @@ -88,7 +88,7 @@ The following is a typical DNS-over-HTTPS architecture: | doh-client +--+ Content Delivery Network +--+ (Apache, Nginx, Caddy) | +--------------+ +--------------------------+ +------------------------+ -Although DNS-over-HTTPS can work alone, a HTTP service muxer would be useful as +Although DNS-over-HTTPS can work alone, an HTTP service muxer would be useful as you can host DNS-over-HTTPS along with other HTTPS services. HTTP/2 with at least TLS v1.3 is recommended. OCSP stapling must be enabled, @@ -275,7 +275,7 @@ services: ### Example configuration: DNS-over-TLS -There is no native [DNS-over-TLS](https://en.wikipedia.org/wiki/DNS_over_TLS) support but you can easily add it via nginx: +There is no native [DNS-over-TLS](https://en.wikipedia.org/wiki/DNS_over_TLS) support, but you can easily add it via nginx: ``` stream { server { @@ -294,7 +294,7 @@ this approach does not need a stand-alone daemon to provide the DoT service. ## DNSSEC DNS-over-HTTPS is compatible with DNSSEC, and requests DNSSEC signatures by -default. However signature validation is not built-in. It is highly recommended +default. However, signature validation is not built-in. It is highly recommended that you install `unbound` or `bind` and pass results for them to validate DNS records. An instance of [Pi Hole](https://pi-hole.net) could also be used to validate DNS signatures as well as provide other capabilities. diff --git a/doh-client/client.go b/doh-client/client.go index df43561..e306d2e 100644 --- a/doh-client/client.go +++ b/doh-client/client.go @@ -38,39 +38,40 @@ import ( "sync" "time" - "github.com/m13253/dns-over-https/v2/doh-client/config" - "github.com/m13253/dns-over-https/v2/doh-client/selector" - jsondns "github.com/m13253/dns-over-https/v2/json-dns" "github.com/miekg/dns" "golang.org/x/net/http2" "golang.org/x/net/idna" + + "github.com/m13253/dns-over-https/v2/doh-client/config" + "github.com/m13253/dns-over-https/v2/doh-client/selector" + jsondns "github.com/m13253/dns-over-https/v2/json-dns" ) type Client struct { - conf *config.Config - bootstrap []string - passthrough []string - udpClient *dns.Client - tcpClient *dns.Client - udpServers []*dns.Server - tcpServers []*dns.Server - bootstrapResolver *net.Resolver + httpClientLastCreate time.Time cookieJar http.CookieJar + selector selector.Selector httpClientMux *sync.RWMutex + tcpClient *dns.Client + bootstrapResolver *net.Resolver + udpClient *dns.Client + conf *config.Config httpTransport *http.Transport httpClient *http.Client - httpClientLastCreate time.Time - selector selector.Selector + udpServers []*dns.Server + tcpServers []*dns.Server + passthrough []string + bootstrap []string } type DNSRequest struct { + err error response *http.Response reply *dns.Msg - udpSize uint16 - ednsClientAddress net.IP - ednsClientNetmask uint8 currentUpstream string - err error + ednsClientAddress net.IP + udpSize uint16 + ednsClientNetmask uint8 } func NewClient(conf *config.Config) (c *Client, err error) { @@ -427,7 +428,7 @@ func (c *Client) handlerFunc(w dns.ResponseWriter, r *dns.Msg, isTCP bool) { // https://developers.cloudflare.com/1.1.1.1/dns-over-https/request-structure/ says // returns code will be 200 / 400 / 413 / 415 / 504, some server will return 503, so - // I think if status code is 5xx, upstream must has some problems + // I think if status code is 5xx, upstream must have some problems /*if req.response.StatusCode/100 == 5 { c.selector.ReportUpstreamStatus(upstream, selector.Medium) }*/ diff --git a/doh-client/google.go b/doh-client/google.go index f298ca3..90b75df 100644 --- a/doh-client/google.go +++ b/doh-client/google.go @@ -34,9 +34,10 @@ import ( "strconv" "strings" + "github.com/miekg/dns" + "github.com/m13253/dns-over-https/v2/doh-client/selector" jsondns "github.com/m13253/dns-over-https/v2/json-dns" - "github.com/miekg/dns" ) func (c *Client) generateRequestGoogle(ctx context.Context, w dns.ResponseWriter, r *dns.Msg, isTCP bool, upstream *selector.Upstream) *DNSRequest { @@ -77,7 +78,7 @@ func (c *Client) generateRequestGoogle(ctx context.Context, w dns.ResponseWriter requestURL += fmt.Sprintf("&edns_client_subnet=%s/%d", ednsClientAddress.String(), ednsClientNetmask) } - req, err := http.NewRequest(http.MethodGet, requestURL, nil) + req, err := http.NewRequest(http.MethodGet, requestURL, http.NoBody) if err != nil { log.Println(err) reply := jsondns.PrepareReply(r) diff --git a/doh-client/ietf.go b/doh-client/ietf.go index bf9545c..69ccbe4 100644 --- a/doh-client/ietf.go +++ b/doh-client/ietf.go @@ -35,9 +35,10 @@ import ( "strings" "time" + "github.com/miekg/dns" + "github.com/m13253/dns-over-https/v2/doh-client/selector" jsondns "github.com/m13253/dns-over-https/v2/json-dns" - "github.com/miekg/dns" ) func (c *Client) generateRequestIETF(ctx context.Context, w dns.ResponseWriter, r *dns.Msg, isTCP bool, upstream *selector.Upstream) *DNSRequest { @@ -104,7 +105,7 @@ func (c *Client) generateRequestIETF(ctx context.Context, w dns.ResponseWriter, var req *http.Request if len(requestURL) < 2048 { - req, err = http.NewRequest(http.MethodGet, requestURL, nil) + req, err = http.NewRequest(http.MethodGet, requestURL, http.NoBody) if err != nil { log.Println(err) reply := jsondns.PrepareReply(r) diff --git a/doh-client/main.go b/doh-client/main.go index ec8a569..0123c46 100644 --- a/doh-client/main.go +++ b/doh-client/main.go @@ -26,7 +26,6 @@ package main import ( "flag" "fmt" - "io" "log" "os" "runtime" @@ -37,7 +36,7 @@ import ( func checkPIDFile(pidFile string) (bool, error) { retry: - f, err := os.OpenFile(pidFile, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666) + f, err := os.OpenFile(pidFile, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o666) if os.IsExist(err) { pidStr, err := os.ReadFile(pidFile) if err != nil { @@ -63,7 +62,7 @@ retry: return false, err } defer f.Close() - _, err = io.WriteString(f, strconv.FormatInt(int64(os.Getpid()), 10)) + _, err = f.WriteString(strconv.FormatInt(int64(os.Getpid()), 10)) if err != nil { return false, err } diff --git a/doh-client/selector/lvsWRRSelector.go b/doh-client/selector/lvsWRRSelector.go index 0abe5a0..940bbd9 100644 --- a/doh-client/selector/lvsWRRSelector.go +++ b/doh-client/selector/lvsWRRSelector.go @@ -80,7 +80,7 @@ func (ls *LVSWRRSelector) StartEvaluate() { acceptType = "application/dns-message" } - req, err := http.NewRequest(http.MethodGet, upstreamURL, nil) + req, err := http.NewRequest(http.MethodGet, upstreamURL, http.NoBody) if err != nil { /*log.Println("upstream:", upstreamURL, "type:", typeMap[upstream.Type], "check failed:", err) continue*/ diff --git a/doh-client/selector/nginxWRRSelector.go b/doh-client/selector/nginxWRRSelector.go index a535a28..fafb5b6 100644 --- a/doh-client/selector/nginxWRRSelector.go +++ b/doh-client/selector/nginxWRRSelector.go @@ -73,7 +73,7 @@ func (ws *NginxWRRSelector) StartEvaluate() { acceptType = "application/dns-message" } - req, err := http.NewRequest(http.MethodGet, upstreamURL, nil) + req, err := http.NewRequest(http.MethodGet, upstreamURL, http.NoBody) if err != nil { /*log.Println("upstream:", upstreamURL, "type:", typeMap[upstream.Type], "check failed:", err) continue*/ @@ -110,7 +110,7 @@ func (ws *NginxWRRSelector) StartEvaluate() { }() } -// nginx wrr like +// nginx wrr like. func (ws *NginxWRRSelector) Get() *Upstream { var ( total int32 diff --git a/doh-client/selector/randomSelector.go b/doh-client/selector/randomSelector.go index cd2880c..8a3ca7b 100644 --- a/doh-client/selector/randomSelector.go +++ b/doh-client/selector/randomSelector.go @@ -7,7 +7,7 @@ import ( ) func init() { - rand.Seed(time.Now().UnixNano()) + rand.NewSource(time.Now().UnixNano()) } type RandomSelector struct { diff --git a/doh-server/config.go b/doh-server/config.go index 8fb6c76..767069b 100644 --- a/doh-server/config.go +++ b/doh-server/config.go @@ -31,21 +31,21 @@ import ( ) type config struct { - Listen []string `toml:"listen"` + TLSClientAuthCA string `toml:"tls_client_auth_ca"` LocalAddr string `toml:"local_addr"` Cert string `toml:"cert"` Key string `toml:"key"` Path string `toml:"path"` + DebugHTTPHeaders []string `toml:"debug_http_headers"` + Listen []string `toml:"listen"` Upstream []string `toml:"upstream"` Timeout uint `toml:"timeout"` Tries uint `toml:"tries"` Verbose bool `toml:"verbose"` - DebugHTTPHeaders []string `toml:"debug_http_headers"` LogGuessedIP bool `toml:"log_guessed_client_ip"` ECSAllowNonGlobalIP bool `toml:"ecs_allow_non_global_ip"` ECSUsePreciseIP bool `toml:"ecs_use_precise_ip"` TLSClientAuth bool `toml:"tls_client_auth"` - TLSClientAuthCA string `toml:"tls_client_auth_ca"` } func loadConfig(path string) (*config, error) { diff --git a/doh-server/server.go b/doh-server/server.go index 35b26c2..8efd584 100644 --- a/doh-server/server.go +++ b/doh-server/server.go @@ -53,11 +53,11 @@ type Server struct { type DNSRequest struct { request *dns.Msg response *dns.Msg - transactionID uint16 currentUpstream string - isTailored bool - errcode int errtext string + errcode int + transactionID uint16 + isTailored bool } func NewServer(conf *config) (*Server, error) { @@ -285,7 +285,7 @@ func (s *Server) handlerFunc(w http.ResponseWriter, r *http.Request) { func (s *Server) findClientIP(r *http.Request) net.IP { noEcs := r.URL.Query().Get("no_ecs") - if strings.ToLower(noEcs) == "true" { + if strings.EqualFold(noEcs, "true") { return nil }