From ce656ac3f7eaf038e0d604153dbcc04155e012a2 Mon Sep 17 00:00:00 2001 From: gdm85 Date: Sun, 15 Apr 2018 13:40:26 +0200 Subject: [PATCH 1/2] Add client support for multiple listen addresses --- doh-client/client.go | 67 ++++++++++++++++++++------------------ doh-client/config.go | 6 ++-- doh-client/doh-client.conf | 4 ++- 3 files changed, 41 insertions(+), 36 deletions(-) diff --git a/doh-client/client.go b/doh-client/client.go index 0c860ea..05f909a 100644 --- a/doh-client/client.go +++ b/doh-client/client.go @@ -42,8 +42,8 @@ import ( type Client struct { conf *config bootstrap []string - udpServer *dns.Server - tcpServer *dns.Server + udpServers []*dns.Server + tcpServers []*dns.Server bootstrapResolver *net.Resolver cookieJar *cookiejar.Jar httpClientMux *sync.RWMutex @@ -64,16 +64,21 @@ func NewClient(conf *config) (c *Client, err error) { c = &Client{ conf: conf, } - c.udpServer = &dns.Server{ - Addr: conf.Listen, - Net: "udp", - Handler: dns.HandlerFunc(c.udpHandlerFunc), - UDPSize: 4096, - } - c.tcpServer = &dns.Server{ - Addr: conf.Listen, - Net: "tcp", - Handler: dns.HandlerFunc(c.tcpHandlerFunc), + + udpH := dns.HandlerFunc(c.udpHandlerFunc) + tcpH := dns.HandlerFunc(c.tcpHandlerFunc) + for _, addr := range conf.Listen { + c.udpServers = append(c.udpServers, &dns.Server{ + Addr: addr, + Net: "udp", + Handler: udpH, + UDPSize: 4096, + }) + c.tcpServers = append(c.tcpServers, &dns.Server{ + Addr: addr, + Net: "tcp", + Handler: tcpH, + }) } c.bootstrapResolver = net.DefaultResolver if len(conf.Bootstrap) != 0 { @@ -149,27 +154,25 @@ func (c *Client) newHTTPClient() error { } func (c *Client) Start() error { - result := make(chan error) - go func() { - err := c.udpServer.ListenAndServe() - if err != nil { - log.Println(err) - } - result <- err - }() - go func() { - err := c.tcpServer.ListenAndServe() - if err != nil { - log.Println(err) - } - result <- err - }() - err := <-result - if err != nil { - return err + result := make(chan error, len(c.udpServers)+len(c.tcpServers)) + for _, srv := range append(c.udpServers, c.tcpServers...) { + go func(srv *dns.Server) { + err := srv.ListenAndServe() + if err != nil { + log.Println(err) + } + result <- err + }(srv) } - err = <-result - return err + + for i := 0; i < cap(result); i++ { + err := <-result + if err != nil { + return err + } + } + close(result) + return nil } func (c *Client) handlerFunc(w dns.ResponseWriter, r *dns.Msg, isTCP bool) { diff --git a/doh-client/config.go b/doh-client/config.go index 50a0fcb..808d9b1 100644 --- a/doh-client/config.go +++ b/doh-client/config.go @@ -30,7 +30,7 @@ import ( ) type config struct { - Listen string `toml:"listen"` + Listen []string `toml:"listen"` UpstreamGoogle []string `toml:"upstream_google"` UpstreamIETF []string `toml:"upstream_ietf"` Bootstrap []string `toml:"bootstrap"` @@ -50,8 +50,8 @@ func loadConfig(path string) (*config, error) { return nil, &configError{fmt.Sprintf("unknown option %q", key.String())} } - if conf.Listen == "" { - conf.Listen = "127.0.0.1:53" + if len(conf.Listen) == 0 { + conf.Listen = []string{"127.0.0.1:53"} } if len(conf.UpstreamGoogle) == 0 && len(conf.UpstreamIETF) == 0 { conf.UpstreamGoogle = []string{"https://dns.google.com/resolve"} diff --git a/doh-client/doh-client.conf b/doh-client/doh-client.conf index 5844cf2..d26b0d3 100644 --- a/doh-client/doh-client.conf +++ b/doh-client/doh-client.conf @@ -1,5 +1,7 @@ # DNS listen port -listen = "127.0.0.1:53" +listen = [ + "127.0.0.1:53" +] # HTTP path for upstream resolver # If multiple servers are specified, a random one will be chosen each time. From 1abba72898e1d224dccf97b1ca4dcbddcf129d6c Mon Sep 17 00:00:00 2001 From: gdm85 Date: Sun, 15 Apr 2018 13:27:13 +0200 Subject: [PATCH 2/2] Add server support for multiple listen addresses --- doh-server/config.go | 7 ++++--- doh-server/doh-server.conf | 4 +++- doh-server/server.go | 23 ++++++++++++++++++++--- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/doh-server/config.go b/doh-server/config.go index e13aa2d..8264334 100644 --- a/doh-server/config.go +++ b/doh-server/config.go @@ -30,7 +30,7 @@ import ( ) type config struct { - Listen string `toml:"listen"` + Listen []string `toml:"listen"` Cert string `toml:"cert"` Key string `toml:"key"` Path string `toml:"path"` @@ -51,9 +51,10 @@ func loadConfig(path string) (*config, error) { return nil, &configError{fmt.Sprintf("unknown option %q", key.String())} } - if conf.Listen == "" { - conf.Listen = "127.0.0.1:8053" + if len(conf.Listen) == 0 { + conf.Listen = []string{"127.0.0.1:8053"} } + if conf.Path == "" { conf.Path = "/dns-query" } diff --git a/doh-server/doh-server.conf b/doh-server/doh-server.conf index 635277d..4d8afe1 100644 --- a/doh-server/doh-server.conf +++ b/doh-server/doh-server.conf @@ -1,5 +1,7 @@ # HTTP listen port -listen = "127.0.0.1:8053" +listen = [ + "127.0.0.1:8053" +] # TLS certification file cert = "" diff --git a/doh-server/server.go b/doh-server/server.go index fa990de..1cf8f8c 100644 --- a/doh-server/server.go +++ b/doh-server/server.go @@ -75,10 +75,27 @@ func (s *Server) Start() error { if s.conf.Verbose { servemux = handlers.CombinedLoggingHandler(os.Stdout, servemux) } - if s.conf.Cert != "" || s.conf.Key != "" { - return http.ListenAndServeTLS(s.conf.Listen, s.conf.Cert, s.conf.Key, servemux) + listeners := make(chan error, len(s.conf.Listen)) + for _, addr := range s.conf.Listen { + if s.conf.Cert != "" || s.conf.Key != "" { + go func() { + listeners <- http.ListenAndServeTLS(addr, s.conf.Cert, s.conf.Key, servemux) + }() + continue + } + go func() { + listeners <- http.ListenAndServe(addr, servemux) + }() } - return http.ListenAndServe(s.conf.Listen, servemux) + // wait for all handlers + for i := 0; i < cap(listeners); i++ { + err := <-listeners + if err != nil { + return err + } + } + close(listeners) + return nil } func (s *Server) handlerFunc(w http.ResponseWriter, r *http.Request) {