diff options
| author | Shulhan <m.shulhan@gmail.com> | 2019-10-16 21:41:27 +0700 |
|---|---|---|
| committer | Shulhan <m.shulhan@gmail.com> | 2019-10-16 21:49:20 +0700 |
| commit | 711e75f2b58a44b51b4c7a2b47a341c29a5e675a (patch) | |
| tree | 260142d7b71cd24450260443ae94dfe60ca14177 | |
| parent | e1366b601bf8e74b21918fe9121b1e3e30d73b1b (diff) | |
| download | rescached-711e75f2b58a44b51b4c7a2b47a341c29a5e675a.tar.xz | |
all: refactoring configuration file
The configuration file now group into two section: the '[rescached]' and
'[dns "server"]' sections. All of the configuration values are loaded
using ini.Unmarshal instead of using manual parsing.
| -rw-r--r-- | CHANGELOG.adoc | 10 | ||||
| -rw-r--r-- | README.adoc | 71 | ||||
| -rw-r--r-- | cmd/rescached/config.go | 149 | ||||
| -rw-r--r-- | cmd/rescached/main.go | 30 | ||||
| -rw-r--r-- | cmd/rescached/rescached.cfg | 157 | ||||
| -rw-r--r-- | doc/rescached.cfg.adoc | 201 | ||||
| -rw-r--r-- | go.mod | 5 | ||||
| -rw-r--r-- | go.sum | 6 | ||||
| -rw-r--r-- | options.go | 22 | ||||
| -rw-r--r-- | options_test.go | 57 | ||||
| -rw-r--r-- | rescached.go | 6 | ||||
| -rw-r--r-- | testdata/rescached.cfg | 39 |
12 files changed, 336 insertions, 417 deletions
diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 0736ba8..9870d2b 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -12,9 +12,15 @@ and watching changes from system resolv.conf. == Breaking Changes -There are also some major changes on configuration file, +There are also some major changes on configuration file. +All configuration now break into two section '[rescached]' and +'[dns "server"]'. +For more information see new rescached.cfg manual page or an example in +`cmd/rescached/rescached.cfg`. -* "server.parent" option now use URI format instead of IP:PORT. +Some detailed changes are, + +* "parent" option now use URI format instead of IP:PORT. This will allow parent name servers to be UDP, TCP, and/or DoH simultaneously. diff --git a/README.adoc b/README.adoc index 673e5c7..ad1e10e 100644 --- a/README.adoc +++ b/README.adoc @@ -42,27 +42,27 @@ List of current features, - Enable to handle request from UDP and TCP connections - Enable to forward request using UDP or TCP - Load and serve addresses and hostnames in +/etc/hosts+ -- Load and serve hosts formated files inside directory +- Load and serve hosts formatted files inside directory +/etc/rescached/hosts.d/+ - Blocking ads and/or malicious websites through host list in +/etc/rescached/hosts.d/hosts.block+ - Support loading and serving master (zone) file format from +/etc/rescached/master.d+ - Integration with openresolv -- Support DNS over HTTPS (DoH) (draft 14) +- Support DNS over HTTPS (DoH) (RFC 8484) === BEHIND THE DNS When you open a website, let say 'kilabit.info', in a browser, the first thing that browser do is to translate name address 'kilabit.info' into an internet -address (e.g.: 103.200.4.162) so browser can make a connection to +address (for example to 35.240.172.103) so browser can make a connection to 'kilabit.info' server. How browser do that? First, it will send query to one of DNS server listed in your system -configuration (i.e. +/etc/resolv.conf+ in Linux). +configuration (in example, +/etc/resolv.conf+ in Linux). Then, if your DNS server also "caching" the name that you requested, it will reply the answer (internet address) directly, if it is not then it will ask their parent DNS server. @@ -76,7 +76,7 @@ their parent DNS server. If you browsing frequently on the same site, hitting the refresh button, opening another page on the same website, etc; this procedures will always repeated every times, not including all external links like ads, social media -button, or javascripts from an other server. +button, or JavaScript from an other server. To make this repetitive procedures less occurred, you can run +rescached+ in your personal computer. @@ -100,7 +100,7 @@ The only request that will be send to your DNS server is the one that does not already exist in +rescached+ cache. -=== HOW CACHE WORKS IN +RESCACHED+ +=== HOW CACHE WORKS This section explain the simplified version of how internal program works. @@ -125,8 +125,8 @@ The following table illustrate list of caches in memory, +---------------------+------------------+ ---- -Every +cache.prune_delay+ (e.g. 5 minutes), rescached will try to pruning old -records from cache. +Every +cache.prune_delay+ (let say every 5 minutes), rescached will try to +pruning old records from cache. If the accessed-at value of record in cache is less than, ---- @@ -179,12 +179,12 @@ We use directory "/etc/rescached" as configuration directory. + If you want your program running each time the system is starting up you can create a system startup script (or system service). -For system using systemd, uou can see an example for +systemd+ service in +For OS using systemd, you can see an example for +systemd+ service in +scripts/rescached.service+. For system using launchd (macOS), you can see an example in +scripts/info.kilabit.rescached.plist+. + -This step is really different between each system, consult your distribution +This step could be different between systems, consult your distribution wiki, forum, or mailing-list on how to create system startup script. ==== AUTOMATIC INSTALLATION ON LINUX @@ -216,7 +216,7 @@ You can then load the rescached service using launchd, * Set your parent DNS server. + Edit rescached configuration, +/etc/rescached/rescached.cfg+, change the value -of +server.parent+ based on your preferred DNS server. +of +parent+ based on your preferred DNS server. * Set the cache prune delay and threshold + @@ -251,8 +251,8 @@ Rescached support loading master file format. Unlike hosts file format, where each domain name is only mapped to type A (IPv4 address), in master file, one can define other type that known to rescached. -All files defined `dir.master` configuration are considered as master file and -will be loaded by rescached only if the config is not empty. +All files defined +dir.master+ configuration are considered as master file and +will be loaded by rescached only if the configuration is not empty. Example of master file, @@ -275,10 +275,10 @@ my-site.com A 10.8.0.1 Here we defined the variable origin for root domain "my-site.vm." with minimum time-to-live (TTL) to 3600 seconds. -If no "$origin" variable is defined, rescached will use the file name as -origin. +If no "$ORIGIN" variable is defined, rescached will use the file name as +$ORIGIN's value. -The "@" character will be replaced with the value of origin. +The "@" character will be replaced with the value of $ORIGIN. The first resource record (RR) is defining an IPv4 address for "my-site.vm." to "192.168.56.10". @@ -299,7 +299,7 @@ For more information about format of master file see RFC 1035 section 5. === INTEGRATION WITH OPENRESOLV -rescached can detect change on file generated by resolvconf. +Rescached can detect change on file generated by resolvconf. To use this feature unset the "file.resolvconf" in configuration file and set either "dnsmasq_resolv", "pdnsd_resolv", or "unbound_conf" in "/etc/resolvconf.conf" to point to file referenced in "file.resolvconf". @@ -310,25 +310,28 @@ For more information see *rescached.cfg*(5). === INTEGRATION WITH DNS OVER HTTPS DNS over HTTPS (DoH) is the new protocol to query DNS through HTTPS layer. -To enable this feature rescached must run as DoH server using the provided -self-signed certificate or your own certificate. +Rescached support serving DNS over HTTPS or as client to parent DoH +nameservers. +To enable this feature rescached provided TLS certificate and private key. Example configuration in *rescached.cfg*, ---- - server.doh.parent = https://cloudflare-dns.com/dns-query - server.doh.certificate = /etc/rescached/localhost.cert.pem - server.doh.certificate.key = /etc/rescached/localhost.key.pem + [rescached] + tls.certificate = /etc/rescached/localhost.cert.pem + tls.private_key = /etc/rescached/localhost.key.pem + + [dns "server"] + parent = https://kilabit.info/dns-query + tls.allow_insecure = false ---- -If the "server.doh.parent" is using self-signed certificate, you can set -"server.doh.allow_insecure" to true. +If the parent nameserver is using self-signed certificate, you can set +"tls.allow_insecure" to true. Using the above configuration, rescached will serve DoH queries on -*https://localhost/dns-query*. -Only query to port 443 will be forwarded to "+server.doh.parent+". -Queries to port 53, either with UDP or TCP, will be forwarded to -"+server.parent+" name servers as usual. +*https://localhost/dns-query* on port 443 and UDP queries on port 53. +All queries to both locations will be forwarded to parent nameserver. This feature can be tested using Firefox Nightly by updating the configuration in "about:config" into, @@ -342,7 +345,7 @@ in "about:config" into, Since we are using `mode=3`, the `network.trr.bootstrapAddress` is required so Firefox Nightly can resolve "localhost" to "127.0.0.1". If you use the provided self-signed certificate, you must import and/or enable -an exception for it manually in Firefox Nightly (e.g. by opening +an exception for it manually in Firefox Nightly (for example. by opening `https://localhost/dns-query` in new tab and accept security risk). To check if DoH works, first, set the `debug` option to `1`, and @@ -352,9 +355,9 @@ Run Firefox Nightly and open any random website. At the terminal you will see output from rescached which looks like these, ---- -... rescached[10742]: < request: 4 - &{Name:cs2... -... rescached[10742]: - expired: 413 1548503139 &{Name:cs2... -... rescached[10742]: + update : - 1548503139 &{Name:cs2... +... rescached[808]: dns: ^ DoH https://kilabit.info/dns-query 41269:&{Name:id.wikipedia.org Type:A} +... rescached[808]: dns: < UDP 45873:&{Name:id.wikipedia.org Type:AAAA} +... rescached[808]: dns: + UDP 41269:&{Name:id.wikipedia.org Type:A} ---- If you see number "4" in request line, "< request: 4", thats indicated that @@ -390,7 +393,7 @@ This program developed with references to, 'RFC1035':: Domain Names - Implementation and Specification. 'RFC1886':: DNS Extensions to support IP version 6. 'RFC2782':: A DNS RR for specifying the location of services (DNS SRV) -'draft-ietf-doh-dns-over-https-14':: DNS Queries over HTTPS (DoH) +'RFC8484':: DNS Queries over HTTPS (DoH) == BUGS @@ -413,7 +416,7 @@ AAAA:: A host address in IPv6 SRV:: Service locator OPT:: This is a "pseudo DNS record type" needed to support EDNS -+rescached+ only run and tested in Linux system. ++rescached+ only run and tested in Linux and macOS system. Technically, if it can compiled, it will run in any operating system. For request of features and/or bugs report please submitted through web at diff --git a/cmd/rescached/config.go b/cmd/rescached/config.go deleted file mode 100644 index 56831bf..0000000 --- a/cmd/rescached/config.go +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2018, Shulhan <ms@kilabit.info>. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package main - -import ( - "crypto/tls" - "log" - "strconv" - "strings" - "time" - - "github.com/shuLhan/share/lib/debug" - "github.com/shuLhan/share/lib/dns" - "github.com/shuLhan/share/lib/ini" - libnet "github.com/shuLhan/share/lib/net" - - rescached "github.com/shuLhan/rescached-go/v3" -) - -// List of config sections. -const ( - cfgSecRescached = "rescached" -) - -func parseConfig(file string) (opts *rescached.Options) { - opts = rescached.NewOptions() - - cfg, err := ini.Open(file) - if err != nil { - return opts - } - - 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) - - parseNSParent(cfg, opts) - parseListen(cfg, opts) - - 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) - - if len(dohCertFile) > 0 && len(dohPrivateKey) > 0 { - cert, err := tls.LoadX509KeyPair(dohCertFile, dohPrivateKey) - if err != nil { - log.Println("rescached: error loading certificate: " + err.Error()) - } else { - opts.DoHCertificate = &cert - } - } - - return opts -} - -func parseNSParent(cfg *ini.Ini, opts *rescached.Options) { - parents := cfg.Gets(cfgSecRescached, "", "server.parent") - - for _, ns := range parents { - ns = strings.TrimSpace(ns) - if len(ns) > 0 { - opts.NameServers = append(opts.NameServers, ns) - } - } -} - -func parseListen(cfg *ini.Ini, opts *rescached.Options) { - listen, _ := cfg.Get(cfgSecRescached, "", "server.listen", "127.0.0.1") - - _, ip, port := libnet.ParseIPPort(listen, dns.DefaultPort) - if ip == nil { - log.Printf("Invalid server.listen: '%s', using default\n", - listen) - return - } - - opts.IPAddress = ip.String() - opts.Port = port -} - -func parseDoHPort(cfg *ini.Ini, opts *rescached.Options) { - v, _ := cfg.Get(cfgSecRescached, "", "server.doh.listen.port", "443") - port, err := strconv.Atoi(v) - if err != nil { - port = int(dns.DefaultDoHPort) - } - - opts.DoHPort = uint16(port) -} - -func parseTimeout(cfg *ini.Ini, opts *rescached.Options) { - v, _ := cfg.Get(cfgSecRescached, "", "server.timeout", "6") - timeout, err := strconv.Atoi(v) - if err != nil { - return - } - - opts.Timeout = time.Duration(timeout) * time.Second -} - -func parseCachePruneDelay(cfg *ini.Ini, opts *rescached.Options) { - v, ok := cfg.Get(cfgSecRescached, "", "cache.prune_delay", "") - if !ok { - return - } - - v = strings.TrimSpace(v) - - var err error - - opts.PruneDelay, err = time.ParseDuration(v) - if err != nil { - return - } -} - -func parseCacheThreshold(cfg *ini.Ini, opts *rescached.Options) { - v, ok := cfg.Get(cfgSecRescached, "", "cache.prune_threshold", "") - if !ok { - return - } - - v = strings.TrimSpace(v) - - var err error - - opts.PruneThreshold, err = time.ParseDuration(v) - if err != nil { - return - } -} - -func parseDebugLevel(cfg *ini.Ini) { - v, ok := cfg.Get(cfgSecRescached, "", "debug", "") - if !ok { - return - } - - debug.Value, _ = strconv.Atoi(v) -} diff --git a/cmd/rescached/main.go b/cmd/rescached/main.go index b79c240..b0b780b 100644 --- a/cmd/rescached/main.go +++ b/cmd/rescached/main.go @@ -5,8 +5,10 @@ package main import ( + "crypto/tls" "flag" "fmt" + "io/ioutil" "log" "os" "os/signal" @@ -14,10 +16,38 @@ import ( "time" "github.com/shuLhan/share/lib/debug" + "github.com/shuLhan/share/lib/ini" rescached "github.com/shuLhan/rescached-go/v3" ) +func parseConfig(file string) (opts *rescached.Options) { + opts = rescached.NewOptions() + + cfg, err := ioutil.ReadFile(file) + if err != nil { + return opts + } + + err = ini.Unmarshal(cfg, opts) + if err != nil { + return opts + } + + if len(opts.TLSCertFile) > 0 && len(opts.TLSPrivateKey) > 0 { + cert, err := tls.LoadX509KeyPair(opts.TLSCertFile, opts.TLSPrivateKey) + if err != nil { + log.Println("rescached: error loading certificate: " + err.Error()) + } else { + opts.TLSCertificate = &cert + } + } + + debug.Value = opts.Debug + + return opts +} + func createRescachedServer(fileConfig string) *rescached.Server { opts := parseConfig(fileConfig) diff --git a/cmd/rescached/rescached.cfg b/cmd/rescached/rescached.cfg index 8474e4e..de8d747 100644 --- a/cmd/rescached/rescached.cfg +++ b/cmd/rescached/rescached.cfg @@ -1,96 +1,19 @@ -[RESCACHED] +[rescached] ## -## server.parent:: List of parent DNS servers, separated by commas. -## -## Format:: -## -## nameservers = [ scheme "://"] ( ip-address / domain-name ) [ ":" port ] -## scheme = ( "tcp" / "udp" / "https") -## -## Default scheme:: udp -## Default address:: (None) -## Default port:: 53 -## - -server.parent=udp://1.1.1.1 -server.parent=udp://1.0.0.1:53 -server.parent=https://cloudflare-dns.com/dns-query - -## -## server.listen:: Local IP address that rescached will listening for client -## request. -## -## Format:: <IP-ADDRESS>:<PORT> -## Default:: 127.0.0.1:53 -## - -server.listen=127.0.0.1:53 - -## Uncomment line below if you want to serve rescached to other computers. -#server.listen = 0.0.0.0:53 - -## -## server.doh.listen.port:: port to serve DNS over HTTPS. -## Default:: 443 -## - -#server.doh.listen.port = 443 - -## -## server.doh.certificate:: path to certificate file to serve DNS over HTTPS. +## tls.certificate:: path to certificate file to serve DNS over HTTPS. ## Default:: "" (empty) ## -#server.doh.certificate = /etc/rescached/localhost.cert.pem +#tls.certificate = /etc/rescached/localhost.cert.pem ## -## server.doh.certificate.key:: path to certificate private key file to serve +## tls.private_key:: path to certificate's private key file to serve ## DNS over HTTPS. ## Default:: "" (empty) ## -#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. -## Default:: 6 -## - -#server.timeout=6 - -## -## cache.prune_delay:: Delay for pruning worker. -## Every N seconds/minutes/hours, rescached will traverse all caches and -## remove response that has not been accessed less than "cache.threshold". -## -## Format:: Duration with time unit. Valid time units are "s", "m", "h". -## Default:: 1h -## - -#cache.prune_delay = 1h - -## -## cache.prune_threshold:: The duration when the cache will be considered -## expired. -## -## Format:: Duration. Valid time units are "s", "m", "h". -## Default:: -1h -## - -#cache.prune_threshold = -1h +#tls.private_key = /etc/rescached/localhost.key.pem ## ## dir.hosts:: If its set, rescached will load all (host) files in path. @@ -137,3 +60,73 @@ server.listen=127.0.0.1:53 ## #debug=0 + +[dns "server"] + +## +## parent:: List of parent DNS servers. +## +## Format:: +## +## nameservers = [ scheme "://"] ( ip-address / domain-name ) [ ":" port ] +## scheme = ( "tcp" / "udp" / "https") +## +## Default scheme:: udp +## Default address:: (None) +## Default port:: 53 +## + +parent=udp://35.240.172.103 +parent=tcp://35.240.172.103:53 +parent=https://kilabit.info/dns-query + +## +## listen:: Local IP address that rescached will listening for client +## request. +## +## Format:: <IP-ADDRESS>:<PORT> +## Default:: 127.0.0.1:53 +## + +listen=127.0.0.1:53 + +## Uncomment line below if you want to serve DNS to other computers. +#listen = 0.0.0.0:53 + +## +## http.port:: port to serve DNS over HTTPS. +## Default:: 443 +## + +#http.port = 443 + +## +## tls.allow_insecure:: If its true, allow serving self signed +## certificate on DoH connection. +## +## Format:: true | false +## Default:: false +## + +#tls.allow_insecure = false + +## +## cache.prune_delay:: Delay for pruning worker. +## Every N seconds/minutes/hours, DNS server will traverse all caches and +## remove response that has not been accessed less than "cache.threshold". +## +## Format:: Duration with time unit. Valid time units are "s", "m", "h". +## Default:: 1h +## + +#cache.prune_delay = 1h + +## +## cache.prune_threshold:: The duration when the cache will be considered +## expired. +## +## Format:: Duration. Valid time units are "s", "m", "h". +## Default:: -1h +## + +#cache.prune_threshold = -1h diff --git a/doc/rescached.cfg.adoc b/doc/rescached.cfg.adoc index 6c7ef67..8a2af0a 100644 --- a/doc/rescached.cfg.adoc +++ b/doc/rescached.cfg.adoc @@ -27,37 +27,113 @@ The configuration is using INI format where each options is grouped by header in square bracket: * +[rescached]+ +* +[dns "server"]+ == OPTIONS === +[rescached]+ -This group of options contain the main configuration. +This group of options contain the main configuration that related to +rescached. -[[server.parent]] -==== +server.parent+ +[[tls.certificate]] +==== +tls.certificate+ + +Format:: /path/to/file +Default:: (empty) +Description:: Path to certificate file to serve DNS over HTTPS. + + +[[tls.private_key]] +==== +tls.private_key+ + +Format:: /path/to/file +Default:: (empty) +Description:: Path to certificate private key file to serve DNS over HTTPS. + +[[dir.hosts]] +==== +dir.hosts+ + +Format:: string +Default:: /etc/rescached/hosts.d +Description:: Path to hosts directory. +If set, rescached will load all hosts formatted files inside the directory. +If its empty or unset, it will not loading hosts files even in default +location. + +[[dir.master]] +==== +dir.master+ + +Format:: string +Default:: /etc/rescached/master.d +Description:: Path to master directory. +If set, rescached will load all master files inside directory. +If its empty or unset, it will not loading master file even in default +location. + +[[file.resolvconf]] +==== +file.resolvconf+ + +Format:: /any/path/to/file +Default:: /etc/rescached/resolv.conf +Description:: A path to dynamically generated *resolv.conf*(5) by +*resolvconf*(8). If set, the nameserver values in referenced file will +replace "parent" value and "parent" will become a fallback in +case the referenced file being deleted or can't be parsed. + +To use this config, you must set either "dnsmasq_resolv", "pdnsd_resolv", or +"unbound_conf" in "/etc/resolvconf.conf" to point to +"/etc/rescached/resolv.conf". + +For example, +---- +resolv_conf=/etc/resolv.conf +name_servers=127.0.0.1 +dnsmasq_resolv=/etc/rescached/resolv.conf +#pdnsd_resolv=/etc/rescached/resolv.conf +#unbound_conf=/etc/rescached/resolv.conf +---- + +[[debug]] +==== +debug+ + +Value:: +0::: log nothing. +1::: log startup, request, response, caches, and exit status. +Format:: Number (0 or 1). +Default:: 0 +Description:: This option only used by developer for debugging program or if +user want to monitor what kind of traffic goes out, set this option to 1. + +[[dns_server]] +=== DNS Server options + +This group of options related to DNS server using `[dns "server"]` as section +header. + +[[parent]] +==== +parent+ Format:: ---- -nameservers = nameserver *( "," nameserver ) -nameserver = [ scheme "://"] ( ip-address / domain-name ) [ ":" port ] -scheme = ( "tcp" / "udp" / "https") +parent = "parent = " [ scheme "://"] ( ip-address / domain-name ) [ ":" port ] +scheme = ( "tcp" / "udp" / "https") ---- Default:: -* Address: udp://1.1.1.1 , udp://1.0.0.1 +* Address: udp://35.240.172.103 * Port: 53 Description:: List of parent DNS servers, separated by commas. + When +rescached+ receive a query from client and when it does not have a cached address of query, it will pass the query to those parent server. -+rescached+ use Cloudflare DNS public servers as a default parent name servers ++rescached+ use its own public servers as a default parent name servers if not set. -The reason for this is that Cloudflare DNS public server use a simple and -small size of response/answer. +The reason for this is that its public server use a simple and +small size of response/answer without logging client requests. + Please, do not use OpenDNS server. If certain host-name not found (i.e. typo in host-name), OpenDNS will reply @@ -70,17 +146,17 @@ To check if your parent server reply the unknown host-name with no answer, use Example:: ---- ## Using UDP connection to forward request to parent name server. - server.parent = udp://1.1.1.1 + parent = udp://35.240.172.103 ## Using TCP connection to forward request to parent name server. - server.parent = tcp://1.0.0.1 + parent = tcp://35.240.172.103 ## Using DNS over HTTPS to forward request to parent name server. - server.parent = https://cloudflare-dns.com/dns-query + parent = https://kilabit.info/dns-query ---- -[[server.listen]] -==== +server.listen+ +[[listen]] +==== +listen+ Format:: <IP-ADDRESS>:<PORT> Default:: 127.0.0.1:53 @@ -90,45 +166,22 @@ If you want rescached to serve a query from another host in your local network, change this value to +0.0.0.0:53+. -[[server.doh.certificate]] -==== +server.doh.certificate+ - -Format:: /path/to/file -Default:: (empty) -Description:: Path to certificate file to serve DNS over HTTPS. - - -[[server.doh.certificate.key]] -==== +server.doh.certificate.key+ - -Format:: /path/to/file -Default:: (empty) -Description:: Path to certificate private key file to serve DNS over HTTPS. - - -[[server.doh.allow_insecure]] -==== +server.doh.allow_insecure+ +[[tls.allow_insecure]] +==== +tls.allow_insecure+ Format:: true | false Default:: false Description:: If its true, the certificate is self-signed. -[[server.doh.listen.port]] -==== +server.doh.listen.port+ +[[http.port]] +==== +http.port+ Format:: Number Default:: 443 Description:: Port to serve DNS over HTTPS. -[[server.timeout]] -==== +server.timeout+ - -Format:: Number -Default:: 6 -Description:: This option set the server read and write timeout value. - [[cache.prune_delay]] ==== +cache.prune_delay+ @@ -146,62 +199,6 @@ Default:: -1h Description:: The duration when the cache will be considered expired. Its value must negative and less than -1 minute. -[[dir.hosts]] -==== +dir.hosts+ - -Format:: string -Default:: /etc/rescached/hosts.d -Description:: Path to hosts directory. -If set, rescached will load all hosts formatted files inside the directory. -If its empty or unset, it will not loading hosts files even in default -location. - -[[dir.master]] -==== +dir.master+ - -Format:: string -Default:: /etc/rescached/master.d -Description:: Path to master directory. -If set, rescached will load all master files inside directory. -If its empty or unset, it will not loading master file even in default -location. - -[[file.resolvconf]] -==== +file.resolvconf+ - -Format:: /any/path/to/file -Default:: /etc/rescached/resolv.conf -Description:: 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. - -To use this config, you must set either "dnsmasq_resolv", "pdnsd_resolv", or -"unbound_conf" in "/etc/resolvconf.conf" to point to -"/etc/rescached/resolv.conf". - -For example, ----- -resolv_conf=/etc/resolv.conf -name_servers=127.0.0.1 -dnsmasq_resolv=/etc/rescached/resolv.conf -#pdnsd_resolv=/etc/rescached/resolv.conf -#unbound_conf=/etc/rescached/resolv.conf ----- - - -[[debug]] -==== +debug+ - -Value:: -0::: log nothing. -1::: log startup, request, response, caches, and exit status. -Format:: Number (0 or 1). -Default:: 0 -Description:: This option only used by developer for debugging program or if -user want to monitor what kind of traffic goes out, set this option to 1. - - == EXAMPLE Simple rescached configuration using dnscrypt-proxy that listen on port 54 as @@ -209,8 +206,8 @@ parent resolver, with prune delay set to 60 seconds and threshold also to 60 seconds. .............................................................................. -[rescached] -server.parent=udp://127.0.0.1:54 +[dns "server"] +parent=udp://127.0.0.1:54 cache.prune_delay=60s cache.prune_threshold=60s .............................................................................. @@ -222,12 +219,12 @@ Save the above script into +rescached.cfg+ and run it, == AUTHOR -+rescached+ is developed by M. Shulhan (ms@kilabit.info). ++rescached+ is developed by M. Shulhan (m.shulhan@gmail.com). == LICENSE -Copyright 2018, M. Shulhan (ms@kilabit.info). +Copyright 2018, M. Shulhan (m.shulhan@gmail.com). All rights reserved. Use of this source code is governed by a BSD-style license that can be found @@ -2,4 +2,7 @@ module github.com/shuLhan/rescached-go/v3 go 1.11 -require github.com/shuLhan/share v0.8.3-0.20190928194720-61dcfc67b113 +require ( + github.com/shuLhan/share v0.9.1-0.20191016132846-c698f9750a2a + golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582 // indirect +) @@ -1,10 +1,12 @@ -github.com/shuLhan/share v0.8.3-0.20190928194720-61dcfc67b113 h1:RTCqj1aGMN+BDvzVx2gqtgKjlCRJedmylN/F9G5s03E= -github.com/shuLhan/share v0.8.3-0.20190928194720-61dcfc67b113/go.mod h1:1+SBspKy8sF3BkQ83Jov/CDul+2e4Y3nr+izWC3hDhI= +github.com/shuLhan/share v0.9.1-0.20191016132846-c698f9750a2a h1:KEpcbL7cEpR7Tsk87TKp5Uov7rgB79dMm4rnxP6k15A= +github.com/shuLhan/share v0.9.1-0.20191016132846-c698f9750a2a/go.mod h1:1+SBspKy8sF3BkQ83Jov/CDul+2e4Y3nr+izWC3hDhI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190926114937-fa1a29108794/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190926025831-c00fd9afed17 h1:qPnAdmjNA41t3QBTx2mFGf/SD1IoslhYu7AmdsVzCcs= golang.org/x/net v0.0.0-20190926025831-c00fd9afed17/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582 h1:p9xBe/w/OzkeYVKm234g55gMdD1nSIooTir5kV11kfA= +golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -6,7 +6,6 @@ package rescached import ( "fmt" - "time" "github.com/shuLhan/share/lib/debug" "github.com/shuLhan/share/lib/dns" @@ -19,10 +18,12 @@ import ( // type Options struct { dns.ServerOptions - Timeout time.Duration - FileResolvConf string - DirHosts string - DirMaster string + TLSCertFile string `ini:"rescached::tls.certificate"` + TLSPrivateKey string `ini:"rescached::tls.private_key"` + DirHosts string `ini:"rescached::dir.hosts"` + DirMaster string `ini:"rescached::dir.master"` + FileResolvConf string `ini:"rescached::file.resolvconf"` + Debug int `ini:"rescached::debug"` } // @@ -31,10 +32,8 @@ type Options struct { func NewOptions() *Options { return &Options{ ServerOptions: dns.ServerOptions{ - IPAddress: "127.0.0.1", + ListenAddress: "127.0.0.1:53", }, - - Timeout: 6 * time.Second, } } @@ -42,11 +41,8 @@ func NewOptions() *Options { // init check and initialize the Options instance with default values. // func (opts *Options) init() { - if len(opts.IPAddress) == 0 { - opts.IPAddress = "127.0.0.1" - } - if opts.Timeout <= 0 || opts.Timeout > (6*time.Second) { - opts.Timeout = 6 * time.Second + if len(opts.ListenAddress) == 0 { + opts.ListenAddress = "127.0.0.1:53" } if len(opts.FileResolvConf) > 0 { _, _ = opts.loadResolvConf() diff --git a/options_test.go b/options_test.go new file mode 100644 index 0000000..0cd78d5 --- /dev/null +++ b/options_test.go @@ -0,0 +1,57 @@ +// Copyright 2019, Shulhan <m.shulhan@gmail.com>. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rescached + +import ( + "testing" + + "github.com/shuLhan/share/lib/dns" + "github.com/shuLhan/share/lib/ini" + "github.com/shuLhan/share/lib/test" +) + +func TestOptions(t *testing.T) { + cases := []struct { + desc string + content string + exp *Options + expError string + }{{ + desc: "With empty content", + exp: &Options{}, + }, { + desc: "With multiple parents", + content: `[dns "server"] +listen = 127.0.0.1:53 +parent = udp://35.240.172.103 +parent = https://kilabit.info/dns-query +`, + exp: &Options{ + ServerOptions: dns.ServerOptions{ + ListenAddress: "127.0.0.1:53", + NameServers: []string{ + "udp://35.240.172.103", + "https://kilabit.info/dns-query", + }, + }, + }, + }} + + for _, c := range cases { + t.Log(c.desc) + + got := &Options{ + ServerOptions: dns.ServerOptions{}, + } + + err := ini.Unmarshal([]byte(c.content), got) + if err != nil { + test.Assert(t, "error", c.expError, err.Error(), true) + continue + } + + test.Assert(t, "Options", c.exp, got, true) + } +} diff --git a/rescached.go b/rescached.go index 954f24c..cc08173 100644 --- a/rescached.go +++ b/rescached.go @@ -57,10 +57,8 @@ func New(opts *Options) (srv *Server, err error) { // it. // func (srv *Server) Start() (err error) { - fmt.Printf("= Listening on UDP and TCP at '%s:%d'\n", - srv.opts.IPAddress, srv.opts.Port) - fmt.Printf("= Listening on DoH at '%s:%d'\n", srv.opts.IPAddress, - srv.opts.DoHPort) + fmt.Printf("= Listening on %q (UDP and TCP) and port %d for HTTP(S)\n", + srv.opts.ListenAddress, srv.opts.HTTPPort) if len(srv.opts.FileResolvConf) > 0 { _, err = libio.NewWatcher(srv.opts.FileResolvConf, 0, srv.watchResolvConf) diff --git a/testdata/rescached.cfg b/testdata/rescached.cfg index 83676a4..41a786b 100644 --- a/testdata/rescached.cfg +++ b/testdata/rescached.cfg @@ -1,46 +1,29 @@ -[RESCACHED] +[rescached] + +[dns "server"] ## -## server.parent:: List of parent DNS servers, separated by commas. +## parent:: List of parent DNS servers, separated by commas. ## ## Format:: <IP-ADDRESS:PORT> , ... -## Default address:: 1.1.1.1, 1.0.0.1 +## Default address:: 35.240.172.103 ## Default port:: 53 ## -#server.parent=1.1.1.1, 1.0.0.1:53 - -## -## server.parent.connection:: Type of connection to parent server. -## -## Format:: tcp | udp -## Default:: udp -## - -server.parent.connection=udp -#server.parent.connection=tcp +#parent=35.240.172.103 ## -## server.listen:: Local IP address that rescached will listening for client +## listen:: Local IP address that rescached will listening for client ## request. ## ## Format:: <IP-ADDRESS>:<PORT> ## Default:: 127.0.0.1:53 ## -server.listen=127.0.0.1:5353 +listen=127.0.0.1:5353 ## Uncomment line below if you want to serve rescached to other computers. -#server.listen=0.0.0.0:53 - -## -## server.timeout:: Timeout value, in seconds, for sending and waiting -## packet from client or parent server. -## Format:: any number from 300 to 2147483647. -## Default:: 6 -## - -#server.timeout=6 +#listen=0.0.0.0:53 ## ## cache.prune_delay:: Delay for pruning worker. @@ -63,14 +46,14 @@ server.listen=127.0.0.1:5353 #cache.threshold = -1h ## -## hosts_d.path:: If its set, rescached will load all (host) files in path. +## dir.hosts:: If its set, rescached will load all (host) files in path. ## if its empty, it will skip loading hosts files event in default location. ## ## Format : string. ## Default : /etc/rescached/hosts.d ## -#hosts_d.path=/etc/rescached/hosts.d +#dir.hosts=/etc/rescached/hosts.d ## ## debug:: If its not zero, rescached will print debugging information to |
