From a26e437b5dbd4c2fe9100634669b52bbada26c4c Mon Sep 17 00:00:00 2001 From: nadoo <287492+nadoo@users.noreply.github.com> Date: Tue, 7 Aug 2018 19:43:52 +0800 Subject: [PATCH] dns: add settings dnstimeout/dnsmaxttl/dnsminttl --- README.md | 2 +- conf.go | 20 +++++++++++++------- config/glider.conf.example | 6 ++++++ dns/client.go | 32 +++++++++++++++++++++----------- dns/server.go | 4 ++-- main.go | 10 ++++++++-- rule.go | 2 +- 7 files changed, 52 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 4f17dcf..94c1fc8 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ General: TODO: -- [ ] IPv6 support +- [ ] IPv6 support in ipset manager - [ ] Transparent UDP proxy (iptables tproxy) - [ ] Performance tuning - [ ] TUN/TAP device support diff --git a/conf.go b/conf.go index 1f629b7..b6217a3 100644 --- a/conf.go +++ b/conf.go @@ -17,15 +17,18 @@ var conf struct { Verbose bool Strategy string CheckWebSite string - CheckDuration int + CheckInterval int Listen []string Forward []string RuleFile []string RulesDir string - DNS string - DNSServer []string - DNSRecord []string + DNS string + DNSServer []string + DNSTimeout int + DNSMaxTTL int + DNSMinTTL int + DNSRecord []string IPSet string @@ -36,7 +39,7 @@ func confInit() { flag.BoolVar(&conf.Verbose, "verbose", false, "verbose mode") flag.StringVar(&conf.Strategy, "strategy", "rr", "forward strategy, default: rr") flag.StringVar(&conf.CheckWebSite, "checkwebsite", "www.apple.com", "proxy check HTTP(NOT HTTPS) website address, format: HOST[:PORT], default port: 80") - flag.IntVar(&conf.CheckDuration, "checkduration", 30, "proxy check duration(seconds)") + flag.IntVar(&conf.CheckInterval, "checkduration", 30, "proxy check interval(seconds)") flag.StringSliceUniqVar(&conf.Listen, "listen", nil, "listen url, format: SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS") flag.StringSliceUniqVar(&conf.Forward, "forward", nil, "forward url, format: SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS[,SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS]") flag.StringSliceUniqVar(&conf.RuleFile, "rulefile", nil, "rule file path") @@ -44,6 +47,9 @@ func confInit() { flag.StringVar(&conf.DNS, "dns", "", "dns forwarder server listen address") flag.StringSliceUniqVar(&conf.DNSServer, "dnsserver", []string{"8.8.8.8:53"}, "remote dns server") + flag.IntVar(&conf.DNSTimeout, "dnstimeout", 3, "timeout value used in multiple dnsservers switch(seconds)") + flag.IntVar(&conf.DNSMaxTTL, "dnsmaxttl", 1800, "maximum TTL value for entries in the CACHE(seconds)") + flag.IntVar(&conf.DNSMinTTL, "dnsminttl", 0, "minimum TTL value for entries in the CACHE(seconds)") flag.StringSliceUniqVar(&conf.DNSRecord, "dnsrecord", nil, "custom dns record, format: domain/ip") flag.StringVar(&conf.IPSet, "ipset", "", "ipset name") @@ -116,7 +122,7 @@ type RuleConf struct { Forward []string Strategy string CheckWebSite string - CheckDuration int + CheckInterval int DNSServer []string IPSet string @@ -134,7 +140,7 @@ func NewRuleConfFromFile(ruleFile string) (*RuleConf, error) { f.StringSliceUniqVar(&p.Forward, "forward", nil, "forward url, format: SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS[,SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS]") f.StringVar(&p.Strategy, "strategy", "rr", "forward strategy, default: rr") f.StringVar(&p.CheckWebSite, "checkwebsite", "www.apple.com", "proxy check HTTP(NOT HTTPS) website address, format: HOST[:PORT], default port: 80") - f.IntVar(&p.CheckDuration, "checkduration", 30, "proxy check duration(seconds)") + f.IntVar(&p.CheckInterval, "checkduration", 30, "proxy check interval(seconds)") f.StringSliceUniqVar(&p.DNSServer, "dnsserver", nil, "remote dns server") f.StringVar(&p.IPSet, "ipset", "", "ipset name") diff --git a/config/glider.conf.example b/config/glider.conf.example index c5eb884..c76024b 100644 --- a/config/glider.conf.example +++ b/config/glider.conf.example @@ -125,6 +125,12 @@ dns=:53 # global remote dns server (you can specify different dns server in rule file) dnsserver=8.8.8.8:53 dnsserver=1.1.1.1:53 +# timeout value used in multiple dnsservers switch(seconds) +dnstimeout=3 +# maximum TTL value for entries in the CACHE(seconds) +dnsmaxttl=1800 +# minimum TTL value for entries in the CACHE(seconds) +dnsminttl=0 # custom records dnsrecord=www.example.com/1.2.3.4 dnsrecord=www.example.com/2606:2800:220:1:248:1893:25c8:1946 diff --git a/dns/client.go b/dns/client.go index 7687c99..074f1e6 100644 --- a/dns/client.go +++ b/dns/client.go @@ -13,26 +13,32 @@ import ( "github.com/nadoo/glider/proxy" ) -// DefaultTTL is default ttl in seconds -const DefaultTTL = 600 - // HandleFunc function handles the dns TypeA or TypeAAAA answer type HandleFunc func(Domain, ip string) error +// Config for dns +type Config struct { + Timeout int + MaxTTL int + MinTTL int +} + // Client is a dns client struct type Client struct { dialer proxy.Dialer cache *Cache + config *Config upServers []string upServerMap map[string][]string handlers []HandleFunc } // NewClient returns a new dns client -func NewClient(dialer proxy.Dialer, upServers []string) (*Client, error) { +func NewClient(dialer proxy.Dialer, upServers []string, config *Config) (*Client, error) { c := &Client{ dialer: dialer, cache: NewCache(), + config: config, upServers: upServers, upServerMap: make(map[string][]string), } @@ -75,7 +81,7 @@ func (c *Client) Exchange(reqBytes []byte, clientAddr string, preferTCP bool) ([ return respBytes, err } - ttl := DefaultTTL + ttl := c.config.MinTTL ips := []string{} for _, answer := range resp.Answers { if answer.TYPE == QTypeA || answer.TYPE == QTypeAAAA { @@ -85,14 +91,18 @@ func (c *Client) Exchange(reqBytes []byte, clientAddr string, preferTCP bool) ([ if answer.IP != "" { ips = append(ips, answer.IP) } - if answer.TTL != 0 { - ttl = int(answer.TTL) - } + ttl = int(answer.TTL) } } + if ttl > c.config.MaxTTL { + ttl = c.config.MaxTTL + } else if ttl < c.config.MinTTL { + ttl = c.config.MinTTL + } + // add to cache only when there's a valid ip address - if len(ips) != 0 { + if len(ips) != 0 && ttl > 0 { c.cache.Put(getKey(resp.Question), respBytes, ttl) } @@ -113,9 +123,9 @@ func (c *Client) exchange(qname string, reqBytes []byte, preferTCP bool) (server network = "udp" } - var rc net.Conn servers := c.GetServers(qname) for _, server = range servers { + var rc net.Conn rc, err = dialer.Dial(network, server) if err != nil { log.F("[dns] failed to connect to server %v: %v", server, err) @@ -125,7 +135,7 @@ func (c *Client) exchange(qname string, reqBytes []byte, preferTCP bool) (server // TODO: support timeout setting for different upstream server if len(servers) > 1 { - rc.SetDeadline(time.Now().Add(time.Duration(3) * time.Second)) + rc.SetDeadline(time.Now().Add(time.Duration(c.config.Timeout) * time.Second)) } switch network { diff --git a/dns/server.go b/dns/server.go index 1b6a998..bbd8bc4 100644 --- a/dns/server.go +++ b/dns/server.go @@ -21,8 +21,8 @@ type Server struct { } // NewServer returns a new dns server -func NewServer(addr string, dialer proxy.Dialer, upServers []string) (*Server, error) { - c, err := NewClient(dialer, upServers) +func NewServer(addr string, dialer proxy.Dialer, upServers []string, config *Config) (*Server, error) { + c, err := NewClient(dialer, upServers, config) s := &Server{ addr: addr, Client: c, diff --git a/main.go b/main.go index 3c107ce..0ab0216 100644 --- a/main.go +++ b/main.go @@ -42,7 +42,7 @@ func dialerFromConf() proxy.Dialer { fwdrs = append(fwdrs, fwdr) } - return NewStrategyDialer(conf.Strategy, fwdrs, conf.CheckWebSite, conf.CheckDuration) + return NewStrategyDialer(conf.Strategy, fwdrs, conf.CheckWebSite, conf.CheckInterval) } func main() { @@ -57,7 +57,13 @@ func main() { dialer := NewRuleDialer(conf.rules, dialerFromConf()) ipsetM, _ := NewIPSetManager(conf.IPSet, conf.rules) if conf.DNS != "" { - d, err := dns.NewServer(conf.DNS, dialer, conf.DNSServer) + + dnscfg := &dns.Config{ + Timeout: conf.DNSTimeout, + MaxTTL: conf.DNSMaxTTL, + MinTTL: conf.DNSMinTTL} + + d, err := dns.NewServer(conf.DNS, dialer, conf.DNSServer, dnscfg) if err != nil { log.Fatal(err) } diff --git a/rule.go b/rule.go index b08c3e1..753d3dc 100644 --- a/rule.go +++ b/rule.go @@ -36,7 +36,7 @@ func NewRuleDialer(rules []*RuleConf, gDialer proxy.Dialer) *RuleDialer { fwdrs = append(fwdrs, fwdr) } - sDialer := NewStrategyDialer(r.Strategy, fwdrs, r.CheckWebSite, r.CheckDuration) + sDialer := NewStrategyDialer(r.Strategy, fwdrs, r.CheckWebSite, r.CheckInterval) for _, domain := range r.Domain { rd.domainMap.Store(strings.ToLower(domain), sDialer)