From b7c6359c2cf38ace36b33200a3a58e4197dce41a Mon Sep 17 00:00:00 2001 From: Martin Monperrus Date: Wed, 5 Feb 2020 12:39:36 +0100 Subject: [PATCH 1/3] =?UTF-8?q?@monperrus=20at=20work=20=F0=9F=97=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doh-client/client.go | 22 ++++++++++-- doh-client/config/config.go | 1 + doh-client/selector/hashSelector.go | 54 +++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 doh-client/selector/hashSelector.go diff --git a/doh-client/client.go b/doh-client/client.go index d768f10..1aba324 100644 --- a/doh-client/client.go +++ b/doh-client/client.go @@ -192,8 +192,26 @@ func NewClient(conf *config.Config) (c *Client, err error) { } c.selector = s - - default: + case config.Hash: + if c.conf.Other.Verbose { + log.Println(config.Random, "mode start") + } + s := selector.NewHashSelector() + for _, u := range c.conf.Upstream.UpstreamGoogle { + if err := s.Add(u.URL, selector.Google); err != nil { + return nil, err + } + } + + for _, u := range c.conf.Upstream.UpstreamIETF { + if err := s.Add(u.URL, selector.IETF); err != nil { + return nil, err + } + } + + c.selector = s + + default: if c.conf.Other.Verbose { log.Println(config.Random, "mode start") } diff --git a/doh-client/config/config.go b/doh-client/config/config.go index 01dbe31..a261005 100644 --- a/doh-client/config/config.go +++ b/doh-client/config/config.go @@ -33,6 +33,7 @@ const ( Random = "random" NginxWRR = "weighted_round_robin" LVSWRR = "lvs_weighted_round_robin" + Hash = "hostname_hash" ) type upstreamDetail struct { diff --git a/doh-client/selector/hashSelector.go b/doh-client/selector/hashSelector.go new file mode 100644 index 0000000..553f4e2 --- /dev/null +++ b/doh-client/selector/hashSelector.go @@ -0,0 +1,54 @@ +package selector + +import ( + "errors" + "math/rand" + "time" +) + +func init() { + rand.Seed(time.Now().UnixNano()) +} + +type HashSelector struct { + upstreams []*Upstream +} + +func NewHashSelector() *HashSelector { + return new(HashSelector) +} + +func (rs *HashSelector) Add(url string, upstreamType UpstreamType) (err error) { + switch upstreamType { + case Google: + rs.upstreams = append(rs.upstreams, &Upstream{ + Type: Google, + URL: url, + RequestType: "application/dns-json", + }) + + case IETF: + rs.upstreams = append(rs.upstreams, &Upstream{ + Type: IETF, + URL: url, + RequestType: "application/dns-message", + }) + + default: + return errors.New("unknown upstream type") + } + + return nil +} + +func (rs *HashSelector) Get() *Upstream { + // here, if we have the name to be resolved (a string) + // we could compute the modulo over the size of upstream servers + // something like url.hash()%len(rs.upstreams) + // how to refactor Get() to get the name + return rs.upstreams[url.hash()%len(rs.upstreams)] +} + +func (rs *HashSelector) StartEvaluate() {} + +func (rs *HashSelector) ReportUpstreamStatus(upstream *Upstream, upstreamStatus upstreamStatus) {} From 1a164dfed7293dbf38bea60e135cfee27d4f9ba9 Mon Sep 17 00:00:00 2001 From: Martin Monperrus Date: Wed, 5 Feb 2020 12:43:14 +0100 Subject: [PATCH 2/3] =?UTF-8?q?@monperrus=20at=20work=20=F0=9F=94=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doh-client/client.go | 96 ++++++++++++++++++------------------- doh-client/config/config.go | 2 +- 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/doh-client/client.go b/doh-client/client.go index 1aba324..ad4408d 100644 --- a/doh-client/client.go +++ b/doh-client/client.go @@ -46,30 +46,30 @@ import ( ) 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 - cookieJar http.CookieJar - httpClientMux *sync.RWMutex - httpTransport *http.Transport - httpClient *http.Client + conf *config.Config + bootstrap []string + passthrough []string + udpClient *dns.Client + tcpClient *dns.Client + udpServers []*dns.Server + tcpServers []*dns.Server + bootstrapResolver *net.Resolver + cookieJar http.CookieJar + httpClientMux *sync.RWMutex + httpTransport *http.Transport + httpClient *http.Client httpClientLastCreate time.Time - selector selector.Selector + selector selector.Selector } type DNSRequest struct { - response *http.Response - reply *dns.Msg - udpSize uint16 + response *http.Response + reply *dns.Msg + udpSize uint16 ednsClientAddress net.IP ednsClientNetmask uint8 currentUpstream string - err error + err error } func NewClient(conf *config.Config) (c *Client, err error) { @@ -80,24 +80,24 @@ func NewClient(conf *config.Config) (c *Client, err error) { udpHandler := dns.HandlerFunc(c.udpHandlerFunc) tcpHandler := dns.HandlerFunc(c.tcpHandlerFunc) c.udpClient = &dns.Client{ - Net: "udp", + Net: "udp", UDPSize: dns.DefaultMsgSize, Timeout: time.Duration(conf.Other.Timeout) * time.Second, } c.tcpClient = &dns.Client{ - Net: "tcp", + Net: "tcp", Timeout: time.Duration(conf.Other.Timeout) * time.Second, } for _, addr := range conf.Listen { c.udpServers = append(c.udpServers, &dns.Server{ - Addr: addr, - Net: "udp", + Addr: addr, + Net: "udp", Handler: udpHandler, UDPSize: dns.DefaultMsgSize, }) c.tcpServers = append(c.tcpServers, &dns.Server{ - Addr: addr, - Net: "tcp", + Addr: addr, + Net: "tcp", Handler: tcpHandler, }) } @@ -192,26 +192,26 @@ func NewClient(conf *config.Config) (c *Client, err error) { } c.selector = s - case config.Hash: - if c.conf.Other.Verbose { - log.Println(config.Random, "mode start") - } - s := selector.NewHashSelector() - for _, u := range c.conf.Upstream.UpstreamGoogle { - if err := s.Add(u.URL, selector.Google); err != nil { - return nil, err - } - } - - for _, u := range c.conf.Upstream.UpstreamIETF { - if err := s.Add(u.URL, selector.IETF); err != nil { - return nil, err - } - } - - c.selector = s - - default: + case config.Hash: + if c.conf.Other.Verbose { + log.Println(config.Random, "mode start") + } + s := selector.NewHashSelector() + for _, u := range c.conf.Upstream.UpstreamGoogle { + if err := s.Add(u.URL, selector.Google); err != nil { + return nil, err + } + } + + for _, u := range c.conf.Upstream.UpstreamIETF { + if err := s.Add(u.URL, selector.IETF); err != nil { + return nil, err + } + } + + c.selector = s + + default: if c.conf.Other.Verbose { log.Println(config.Random, "mode start") } @@ -258,12 +258,12 @@ func (c *Client) newHTTPClient() error { Resolver: c.bootstrapResolver, } c.httpTransport = &http.Transport{ - DialContext: dialer.DialContext, + DialContext: dialer.DialContext, ExpectContinueTimeout: 1 * time.Second, - IdleConnTimeout: 90 * time.Second, - MaxIdleConns: 100, + IdleConnTimeout: 90 * time.Second, + MaxIdleConns: 100, MaxIdleConnsPerHost: 10, - Proxy: http.ProxyFromEnvironment, + Proxy: http.ProxyFromEnvironment, TLSHandshakeTimeout: time.Duration(c.conf.Other.Timeout) * time.Second, } if c.conf.Other.NoIPv6 { @@ -280,7 +280,7 @@ func (c *Client) newHTTPClient() error { } c.httpClient = &http.Client{ Transport: c.httpTransport, - Jar: c.cookieJar, + Jar: c.cookieJar, } c.httpClientLastCreate = time.Now() return nil diff --git a/doh-client/config/config.go b/doh-client/config/config.go index a261005..4122ddd 100644 --- a/doh-client/config/config.go +++ b/doh-client/config/config.go @@ -33,7 +33,7 @@ const ( Random = "random" NginxWRR = "weighted_round_robin" LVSWRR = "lvs_weighted_round_robin" - Hash = "hostname_hash" + Hash = "hostname_hash" ) type upstreamDetail struct { From 302181a2bd990b3ae04e787144e86ac9599c214c Mon Sep 17 00:00:00 2001 From: Martin Monperrus Date: Wed, 5 Feb 2020 12:43:57 +0100 Subject: [PATCH 3/3] =?UTF-8?q?@monperrus=20at=20work=20=F0=9F=95=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doh-client/client.go | 88 ++++++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/doh-client/client.go b/doh-client/client.go index ad4408d..576eb53 100644 --- a/doh-client/client.go +++ b/doh-client/client.go @@ -46,30 +46,30 @@ import ( ) 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 - cookieJar http.CookieJar - httpClientMux *sync.RWMutex - httpTransport *http.Transport - httpClient *http.Client + conf *config.Config + bootstrap []string + passthrough []string + udpClient *dns.Client + tcpClient *dns.Client + udpServers []*dns.Server + tcpServers []*dns.Server + bootstrapResolver *net.Resolver + cookieJar http.CookieJar + httpClientMux *sync.RWMutex + httpTransport *http.Transport + httpClient *http.Client httpClientLastCreate time.Time - selector selector.Selector + selector selector.Selector } type DNSRequest struct { - response *http.Response - reply *dns.Msg - udpSize uint16 + response *http.Response + reply *dns.Msg + udpSize uint16 ednsClientAddress net.IP ednsClientNetmask uint8 currentUpstream string - err error + err error } func NewClient(conf *config.Config) (c *Client, err error) { @@ -80,24 +80,24 @@ func NewClient(conf *config.Config) (c *Client, err error) { udpHandler := dns.HandlerFunc(c.udpHandlerFunc) tcpHandler := dns.HandlerFunc(c.tcpHandlerFunc) c.udpClient = &dns.Client{ - Net: "udp", + Net: "udp", UDPSize: dns.DefaultMsgSize, Timeout: time.Duration(conf.Other.Timeout) * time.Second, } c.tcpClient = &dns.Client{ - Net: "tcp", + Net: "tcp", Timeout: time.Duration(conf.Other.Timeout) * time.Second, } for _, addr := range conf.Listen { c.udpServers = append(c.udpServers, &dns.Server{ - Addr: addr, - Net: "udp", + Addr: addr, + Net: "udp", Handler: udpHandler, UDPSize: dns.DefaultMsgSize, }) c.tcpServers = append(c.tcpServers, &dns.Server{ - Addr: addr, - Net: "tcp", + Addr: addr, + Net: "tcp", Handler: tcpHandler, }) } @@ -193,24 +193,24 @@ func NewClient(conf *config.Config) (c *Client, err error) { c.selector = s case config.Hash: - if c.conf.Other.Verbose { - log.Println(config.Random, "mode start") + if c.conf.Other.Verbose { + log.Println(config.Random, "mode start") + } + s := selector.NewHashSelector() + for _, u := range c.conf.Upstream.UpstreamGoogle { + if err := s.Add(u.URL, selector.Google); err != nil { + return nil, err } - s := selector.NewHashSelector() - for _, u := range c.conf.Upstream.UpstreamGoogle { - if err := s.Add(u.URL, selector.Google); err != nil { - return nil, err - } + } + + for _, u := range c.conf.Upstream.UpstreamIETF { + if err := s.Add(u.URL, selector.IETF); err != nil { + return nil, err } - - for _, u := range c.conf.Upstream.UpstreamIETF { - if err := s.Add(u.URL, selector.IETF); err != nil { - return nil, err - } - } - - c.selector = s - + } + + c.selector = s + default: if c.conf.Other.Verbose { log.Println(config.Random, "mode start") @@ -258,12 +258,12 @@ func (c *Client) newHTTPClient() error { Resolver: c.bootstrapResolver, } c.httpTransport = &http.Transport{ - DialContext: dialer.DialContext, + DialContext: dialer.DialContext, ExpectContinueTimeout: 1 * time.Second, - IdleConnTimeout: 90 * time.Second, - MaxIdleConns: 100, + IdleConnTimeout: 90 * time.Second, + MaxIdleConns: 100, MaxIdleConnsPerHost: 10, - Proxy: http.ProxyFromEnvironment, + Proxy: http.ProxyFromEnvironment, TLSHandshakeTimeout: time.Duration(c.conf.Other.Timeout) * time.Second, } if c.conf.Other.NoIPv6 { @@ -280,7 +280,7 @@ func (c *Client) newHTTPClient() error { } c.httpClient = &http.Client{ Transport: c.httpTransport, - Jar: c.cookieJar, + Jar: c.cookieJar, } c.httpClientLastCreate = time.Now() return nil