diff options
| author | Shulhan <ms@kilabit.info> | 2019-04-12 23:07:58 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2019-07-05 00:37:21 +0700 |
| commit | b412fb5853219fee7c0fcad7bab8a72d846d7bc5 (patch) | |
| tree | 59ec94fe15ad69a92920c4378a6ecc5c6109ef48 /cmd | |
| parent | 3bb229101b114153606f7ecec8911c811188bc30 (diff) | |
| download | rescached-b412fb5853219fee7c0fcad7bab8a72d846d7bc5.tar.xz | |
all: refactoring with latest update on dns package
All the server core functionalities (caches and forwarding) now
implemented inside "dns.Server". The main function of this package are
for reading options from configuration file (or from command line options)
and watching changes from system resolv.conf.
There are also some major changes on configuration file.
* "server.parent" option now use URI format instead of IP:PORT.
This will allow parent name servers to be UDP, TCP, and/or DoH
simultaneusly.
* "server.doh.parent" and "server.parent.connection" are removed,
redundant with new "server.parent" format.
* "cache.threshold" is renamed to "cache.prune_threshold".
Diffstat (limited to 'cmd')
| -rw-r--r-- | cmd/rescached/config.go | 121 | ||||
| -rw-r--r-- | cmd/rescached/main.go | 15 | ||||
| -rw-r--r-- | cmd/rescached/rescached.cfg | 61 | ||||
| -rw-r--r-- | cmd/resolver/main.go | 2 | ||||
| -rw-r--r-- | cmd/resolverbench/main.go | 25 |
5 files changed, 61 insertions, 163 deletions
diff --git a/cmd/rescached/config.go b/cmd/rescached/config.go index f3a9c89..dc31cb7 100644 --- a/cmd/rescached/config.go +++ b/cmd/rescached/config.go @@ -5,8 +5,9 @@ package main import ( + "crypto/tls" + "fmt" "log" - "net/url" "strconv" "strings" "time" @@ -32,117 +33,55 @@ func parseConfig(file string) (opts *rescached.Options, err error) { opts = rescached.NewOptions() - opts.FilePID = cfg.GetString(cfgSecRescached, "", "file.pid", - "rescached.pid") - opts.FileResolvConf = cfg.GetString(cfgSecRescached, "", - "file.resolvconf", "") - opts.DoHCert = cfg.GetString(cfgSecRescached, "", - "server.doh.certificate", "") - opts.DoHCertKey = cfg.GetString(cfgSecRescached, "", - "server.doh.certificate.key", "") + opts.FilePID, _ = cfg.Get(cfgSecRescached, "", "file.pid", "rescached.pid") + opts.FileResolvConf, _ = cfg.Get(cfgSecRescached, "", "file.resolvconf", "") + + dohCertFile, _ := cfg.Get(cfgSecRescached, "", "server.doh.certificate", "") + dohPrivateKey, _ := cfg.Get(cfgSecRescached, "", "server.doh.certificate.key", "") opts.DoHAllowInsecure = cfg.GetBool(cfgSecRescached, "", "server.doh.allow_insecure", false) - parseParentConnection(cfg, opts) - err = parseNSParent(cfg, opts) if err != nil { return nil, err } - err = parseDoHParent(cfg, opts) - if err != nil { - return nil, err - } - parseListen(cfg, opts) - opts.DirHosts = cfg.GetString(cfgSecRescached, "", "dir.hosts", "") - opts.DirMaster = cfg.GetString(cfgSecRescached, "", "dir.master", "") + opts.DirHosts, _ = cfg.Get(cfgSecRescached, "", "dir.hosts", "") + opts.DirMaster, _ = cfg.Get(cfgSecRescached, "", "dir.master", "") parseDoHPort(cfg, opts) parseTimeout(cfg, opts) parseCachePruneDelay(cfg, opts) parseCacheThreshold(cfg, opts) parseDebugLevel(cfg) - return opts, nil -} - -func parseNSParent(cfg *ini.Ini, opts *rescached.Options) (err error) { - v, ok := cfg.Get(cfgSecRescached, "", "server.parent") - if !ok { - return - } - - nsParents := strings.Split(v, ",") - - for _, ns := range nsParents { - ns := strings.TrimSpace(ns) - - addr, err := libnet.ParseUDPAddr(ns, dns.DefaultPort) + if len(dohCertFile) > 0 && len(dohPrivateKey) > 0 { + cert, err := tls.LoadX509KeyPair(dohCertFile, dohPrivateKey) if err != nil { - return err + return nil, fmt.Errorf("rescached: error loading certificate: " + err.Error()) } - - opts.NSParents = append(opts.NSParents, addr) + opts.DoHCertificate = &cert } - return nil + return opts, nil } -func parseDoHParent(cfg *ini.Ini, opts *rescached.Options) (err error) { - v, ok := cfg.Get(cfgSecRescached, "", "server.doh.parent") - if !ok { - return - } - - dohParents := strings.Split(v, ",") - - for _, ns := range dohParents { - ns := strings.TrimSpace(ns) - - if !strings.HasPrefix(ns, "https://") { - continue - } - _, err = url.Parse(ns) - if err != nil { - return err - } +func parseNSParent(cfg *ini.Ini, opts *rescached.Options) (err error) { + parents := cfg.Gets(cfgSecRescached, "", "server.parent") - found := false - for _, known := range opts.DoHParents { - if ns == known { - found = true - break - } - } - if !found { - opts.DoHParents = append(opts.DoHParents, ns) + for _, ns := range parents { + ns = strings.TrimSpace(ns) + if len(ns) > 0 { + opts.NameServers = append(opts.NameServers, ns) } } return nil } -func parseParentConnection(cfg *ini.Ini, opts *rescached.Options) { - network := cfg.GetString(cfgSecRescached, "", - "server.parent.connection", "udp") - network = strings.ToLower(network) - - switch network { - case "udp": - opts.ConnType = dns.ConnTypeUDP - case "tcp": - opts.ConnType = dns.ConnTypeTCP - default: - log.Printf("Invalid network: '%s', using default 'udp'\n", - network) - } -} - func parseListen(cfg *ini.Ini, opts *rescached.Options) { - listen := cfg.GetString(cfgSecRescached, "", "server.listen", - "127.0.0.1") + listen, _ := cfg.Get(cfgSecRescached, "", "server.listen", "127.0.0.1") _, ip, port := libnet.ParseIPPort(listen, dns.DefaultPort) if ip == nil { @@ -151,12 +90,12 @@ func parseListen(cfg *ini.Ini, opts *rescached.Options) { return } - opts.ListenAddress = ip.String() - opts.ListenPort = port + opts.IPAddress = ip.String() + opts.Port = port } func parseDoHPort(cfg *ini.Ini, opts *rescached.Options) { - v := cfg.GetString(cfgSecRescached, "", "server.doh.listen.port", "443") + v, _ := cfg.Get(cfgSecRescached, "", "server.doh.listen.port", "443") port, err := strconv.Atoi(v) if err != nil { port = int(dns.DefaultDoHPort) @@ -166,7 +105,7 @@ func parseDoHPort(cfg *ini.Ini, opts *rescached.Options) { } func parseTimeout(cfg *ini.Ini, opts *rescached.Options) { - v := cfg.GetString(cfgSecRescached, "", "server.timeout", "6") + v, _ := cfg.Get(cfgSecRescached, "", "server.timeout", "6") timeout, err := strconv.Atoi(v) if err != nil { return @@ -176,7 +115,7 @@ func parseTimeout(cfg *ini.Ini, opts *rescached.Options) { } func parseCachePruneDelay(cfg *ini.Ini, opts *rescached.Options) { - v, ok := cfg.Get(cfgSecRescached, "", "cache.prune_delay") + v, ok := cfg.Get(cfgSecRescached, "", "cache.prune_delay", "") if !ok { return } @@ -185,14 +124,14 @@ func parseCachePruneDelay(cfg *ini.Ini, opts *rescached.Options) { var err error - opts.CachePruneDelay, err = time.ParseDuration(v) + opts.PruneDelay, err = time.ParseDuration(v) if err != nil { return } } func parseCacheThreshold(cfg *ini.Ini, opts *rescached.Options) { - v, ok := cfg.Get(cfgSecRescached, "", "cache.threshold") + v, ok := cfg.Get(cfgSecRescached, "", "cache.prune_threshold", "") if !ok { return } @@ -201,14 +140,14 @@ func parseCacheThreshold(cfg *ini.Ini, opts *rescached.Options) { var err error - opts.CacheThreshold, err = time.ParseDuration(v) + opts.PruneThreshold, err = time.ParseDuration(v) if err != nil { return } } func parseDebugLevel(cfg *ini.Ini) { - v, ok := cfg.Get(cfgSecRescached, "", "debug") + v, ok := cfg.Get(cfgSecRescached, "", "debug", "") if !ok { return } diff --git a/cmd/rescached/main.go b/cmd/rescached/main.go index feb9376..3e5e8d9 100644 --- a/cmd/rescached/main.go +++ b/cmd/rescached/main.go @@ -24,21 +24,16 @@ func createRescachedServer(fileConfig string) *rescached.Server { log.Fatal(err) } - if debug.Value >= 1 { - fmt.Printf("= config: %+v\n", opts) + rcd, err := rescached.New(opts) + if err != nil { + log.Fatal(err) } - rcd := rescached.New(opts) - err = rcd.WritePID() if err != nil { log.Fatal(err) } - rcd.LoadHostsDir(opts.DirHosts) - rcd.LoadMasterDir(opts.DirMaster) - rcd.LoadHostsFile("") - return rcd } @@ -58,7 +53,6 @@ func debugRuntime(rcd *rescached.Server) { debug.WriteHeapProfile("rescached", true) memHeap.Collect() - println(rcd.CachesStats()) fmt.Printf("= rescached: MemHeap{RelHeapAlloc:%d RelHeapObjects:%d DiffHeapObjects:%d}\n", memHeap.RelHeapAlloc, memHeap.RelHeapObjects, @@ -68,7 +62,6 @@ func debugRuntime(rcd *rescached.Server) { func main() { var ( - err error fileConfig string defConfig = "/etc/rescached/rescached.cfg" ) @@ -86,7 +79,7 @@ func main() { go debugRuntime(rcd) } - err = rcd.Start() + err := rcd.Start() if err != nil { log.Println(err) rcd.Stop() diff --git a/cmd/rescached/rescached.cfg b/cmd/rescached/rescached.cfg index 8e8ec22..b306215 100644 --- a/cmd/rescached/rescached.cfg +++ b/cmd/rescached/rescached.cfg @@ -3,43 +3,18 @@ ## ## server.parent:: List of parent DNS servers, separated by commas. ## -## Format:: <IP-ADDRESS:PORT> -## Default address:: 1.1.1.1, 1.0.0.1 -## Default port:: 53 -## - -server.parent=1.1.1.1, 1.0.0.1:53 - -## -## server.parent.doh:: List of parent DNS servers over HTTPS, separated by -## commas. To be able to use DNS over HTTPS, rescached must also run DoH -## server. That means, certificate and private key files must not be empties. -## -## Format:: https://<domain>/dns-query , ... -## Default:: https://cloudflare-dns.com/dns-query -## - -#server.doh.parent = https://cloudflare-dns.com/dns-query - -## -## server.parent.doh.allow_insecure:: If its true, allow insecure TLS -## connection to parent DoH server. -## -## Format:: true | false -## Default:: false +## Format:: ## - -#server.doh.allow_insecure = false - -## -## server.parent.connection:: Type of connection to parent server. +## nameservers = [ scheme "://"] ( ip-address / domain-name ) [ ":" port ] +## scheme = ( "tcp" / "udp" / "https") ## -## Format:: tcp | udp -## Default:: udp +## Default scheme:: udp +## Default address:: (None) +## Default port:: 53 ## -server.parent.connection=udp -#server.parent.connection=tcp +server.parent=udp://1.1.1.1 +server.parent=udp://1.0.0.1:53 ## ## server.listen:: Local IP address that rescached will listening for client @@ -77,6 +52,16 @@ server.listen=127.0.0.1:53 #server.doh.certificate.key = /etc/rescached/localhost.key.pem ## +## server.doh.allow_insecure:: If its true, allow serving self signed +## certificate on DoH connection. +## +## Format:: true | false +## Default:: false +## + +#server.doh.allow_insecure = false + +## ## server.timeout:: Timeout value, in seconds, for sending and waiting ## packet from client or parent server. ## Format:: any number from 3 to 6. @@ -97,13 +82,14 @@ server.listen=127.0.0.1:53 #cache.prune_delay = 1h ## -## cache.threshold:: The duration when the cache will be considered expired. +## cache.prune_threshold:: The duration when the cache will be considered +## expired. ## ## Format:: Duration. Valid time units are "s", "m", "h". ## Default:: -1h ## -#cache.threshold = -1h +#cache.prune_threshold = -1h ## ## dir.hosts:: If its set, rescached will load all (host) files in path. @@ -138,9 +124,8 @@ file.pid=/var/run/rescached.pid ## ## file.resolvconf:: A path to dynamically generated resolv.conf (5) by -## resolvconf (8). If set, the nameserver values in referenced file will -## replace "server.parent" value and "server.parent" will become a fallback in -## case the referenced file being deleted or can't be parsed. +## resolvconf (8). If set, the nameserver values in referenced file will be +## used as fallback nameserver. ## ## Format:: /any/path/to/file ## Default:: /etc/rescached/resolv.conf diff --git a/cmd/resolver/main.go b/cmd/resolver/main.go index 6af3f47..b47eba3 100644 --- a/cmd/resolver/main.go +++ b/cmd/resolver/main.go @@ -132,7 +132,7 @@ func lookup(opts *options, ns string, timeout time.Duration, qname []byte) *dns. log.Fatal("! Pack:", err) } - res, err := cl.Query(req, nil) + res, err := cl.Query(req) if err != nil { log.Println("! Lookup: ", err) return nil diff --git a/cmd/resolverbench/main.go b/cmd/resolverbench/main.go index 948452e..c84023e 100644 --- a/cmd/resolverbench/main.go +++ b/cmd/resolverbench/main.go @@ -33,46 +33,27 @@ func main() { } var nfail int - res := libdns.NewMessage() fmt.Printf("= Benchmarking with %d messages\n", len(msgs)) timeStart := time.Now() for x := 0; x < len(msgs); x++ { - //fmt.Printf("< Request: %6d %s\n", x, msgs[x].Question) - - _, err = cl.Send(msgs[x], cl.Addr) + res, err := cl.Query(msgs[x]) if err != nil { nfail++ log.Println("! Send error: ", err) continue } - res.Reset() - - _, err = cl.Recv(res) - if err != nil { - nfail++ - log.Println("! Recv error: ", err) - continue - } - - err = res.Unpack() - if err != nil { - nfail++ - log.Println("! Unpack:", err) - continue - } - exp := msgs[x].Answer[0].RData().([]byte) got := res.Answer[0].RData().([]byte) if !bytes.Equal(exp, got) { nfail++ - log.Printf(`! Answer not matched: + log.Printf(`! Answer not matched %s: expecting: %s got: %s -`, exp, got) +`, msgs[x].Question, exp, got) } } timeEnd := time.Now() |
