diff --git a/README.md b/README.md index cfb7929..52faa96 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # go-dnsmasq -*Version 1.0.0* +*Version 1.0.1* go-dnsmasq is a light weight (1.2 MB) DNS caching server/forwarder with minimal filesystem and runtime overhead. @@ -35,20 +35,20 @@ DNS queries are resolved in the style of the GNU libc resolver: | Flag | Description | Default | Environment vars | | ------------------------------ | ----------------------------------------------------------------------------- | ------------- | -------------------- | | --listen, -l | Address to listen on `host[:port]` | 127.0.0.1:53 | $DNSMASQ_LISTEN | -| --default-resolver, -d | Update resolv.conf and make go-dnsmasq the host's primary nameserver | False | $DNSMASQ_DEFAULT | -| --nameservers, -n | Comma-separated list of nameservers `host[:port]` | - | $DNSMASQ_SERVERS | -| --stubzones, -z | Use different nameservers for specific domains `fqdn[,fqdn]/host[:port]` | - | $DNSMASQ_STUB | -| --hostsfile, -f | Full path to a hostsfile | - | $DNSMASQ_HOSTSFILE | -| --hostsfile-poll, -p | How frequently to check hostsfile for changes (seconds, ‘0‘ to disable) | 0 | $DNSMASQ_POLL | -| --search-domains, -s | Specify SEARCH domains (takes precedence over /etc/resolv.conf) `fqdn[,fqdn]` | - | $DNSMASQ_SEARCH | -| --append-search-domains, -a | Qualify queries with SEARCH domains | False | $DNSMASQ_APPEND | +| --default-resolver, -d | Update resolv.conf to make go-dnsmasq the host's nameserver | False | $DNSMASQ_DEFAULT | +| --nameservers, -n | Comma separated list of nameservers `host[:port]` | - | $DNSMASQ_SERVERS | +| --stubzones, -z | Use different nameservers for specific domains `domain[,domain]/host[:port]` | - | $DNSMASQ_STUB | +| --hostsfile, -f | Path to a hostsfile (e.g. ‘/etc/hosts‘) | - | $DNSMASQ_HOSTSFILE | +| --hostsfile-poll, -p | How frequently to poll hostsfile for changes (seconds, ‘0‘ to disable) | 0 | $DNSMASQ_POLL | +| --search-domains, -s | Specify search domains (overrides /etc/resolv.conf) `domain[,domain]` | - | $DNSMASQ_SEARCH | +| --append-search-domains, -a | Resolve queries using search domains | False | $DNSMASQ_APPEND | | --rcache, -r | Capacity of the response cache (‘0‘ to disable cache) | 0 | $DNSMASQ_RCACHE | | --rcache-ttl | TTL for entries in the response cache | 60 | $DNSMASQ_RCACHE_TTL | | --no-rec | Disable recursion | False | $DNSMASQ_NOREC | -| --round-robin | enable round robin of A/AAAA records | False | $DNSMASQ_RR | +| --round-robin | Enable round robin of A/AAAA records | False | $DNSMASQ_RR | | --systemd | Bind to socket(s) activated by Systemd (ignores --listen) | False | $DNSMASQ_SYSTEMD | | --verbose | Enable verbose logging | False | $DNSMASQ_VERBOSE | -| --syslog | Log to syslog | False | $DNSMASQ_SYSLOG | +| --syslog | Enable syslog logging | False | $DNSMASQ_SYSLOG | | --multithreading | Enable multithreading | False | | | --help, -h | Show help | | | | --version, -v | Print the version | | | @@ -80,10 +80,12 @@ go-dnsmasq is available in two versions. The minimal version (`go-dnsmasq-min`) ``` #### Run as a Docker container +[![ImageLayers Size](https://img.shields.io/imagelayers/image-size/janeczku/go-dnsmasq/latest.svg)]() [![Docker Pulls](https://img.shields.io/docker/pulls/janeczku/go-dnsmasq.svg)]() + +Docker Hub trusted builds [available](https://hub.docker.com/r/janeczku/go-dnsmasq/). ```sh -docker run -d -e DNSMASQ_LISTEN=0.0.0.0 -p 53:53/udp -p 53:53 \ - janeczku/go-dnsmasq +docker run -d -p 53:53/udp -p 53:53 janeczku/go-dnsmasq:latest ``` -You can configure go-dnsmasq by passing the corresponding environmental variables with docker run `--env` flag. +You can configure the container by passing the corresponding environmental variables with docker run's `--env` flag. diff --git a/main.go b/main.go index 14c5050..b5ddf31 100644 --- a/main.go +++ b/main.go @@ -26,7 +26,7 @@ import ( ) // var Version string -const Version = "1.0.0" +const Version = "1.0.1" var ( nameservers = []string{} @@ -52,77 +52,72 @@ func main() { cli.StringFlag{ Name: "listen, l", Value: "127.0.0.1:53", - Usage: "listen address: ‘host[:port]‘", + Usage: "Address to listen on `host[:port]`", EnvVar: "DNSMASQ_LISTEN", }, cli.BoolFlag{ Name: "default-resolver, d", - Usage: "make go-dnsmasq the host's primary nameserver (updates resolv.conf)", + Usage: "Update resolv.conf to make go-dnsmasq the host's nameserver", EnvVar: "DNSMASQ_DEFAULT", }, cli.StringFlag{ Name: "nameservers, n", Value: "", - Usage: "comma-separated list of nameservers: ‘host[:port]‘", + Usage: "Comma separated list of nameservers `host[:port]`", EnvVar: "DNSMASQ_SERVERS", }, cli.StringFlag{ Name: "stubzones, z", Value: "", - Usage: "domains to resolve using a specific nameserver: ‘domain[,domain]/host[:port]‘", + Usage: "Use different nameservers for specific domains `domain[,domain]/host[:port]`", EnvVar: "DNSMASQ_STUB", }, cli.StringFlag{ Name: "hostsfile, f", Value: "", - Usage: "full path to hostsfile (e.g. ‘/etc/hosts‘)", + Usage: "Path to a hostsfile (e.g. ‘/etc/hosts‘)", EnvVar: "DNSMASQ_HOSTSFILE", }, cli.IntFlag{ Name: "hostsfile-poll, p", Value: 0, - Usage: "how frequently to poll hostsfile (in seconds, ‘0‘ to disable)", + Usage: "How frequently to poll hostsfile for changes (seconds, ‘0‘ to disable)", EnvVar: "DNSMASQ_POLL", }, cli.StringFlag{ Name: "search-domains, s", Value: "", - Usage: "specify SEARCH domains (takes precedence over resolv.conf): ‘domain[,domain]‘", + Usage: "Specify search domains (overrides /etc/resolv.conf) `domain[,domain]`", EnvVar: "DNSMASQ_SEARCH", }, cli.BoolFlag{ Name: "append-search-domains, a", - Usage: "resolve queries by qualifying them with the search domains", + Usage: "Resolve queries using search domains", EnvVar: "DNSMASQ_APPEND", }, cli.BoolFlag{ Name: "no-rec", - Usage: "disable recursion", + Usage: "Disable recursion", EnvVar: "DNSMASQ_NOREC", }, cli.BoolFlag{ Name: "round-robin", - Usage: "enable round robin of A/AAAA replies", + Usage: "Enable round robin of A/AAAA records", EnvVar: "DNSMASQ_RR", }, - cli.BoolFlag{ - Name: "systemd", - Usage: "bind to socket(s) activated by systemd (ignores --listen)", - EnvVar: "DNSMASQ_SYSTEMD", - }, cli.BoolFlag{ Name: "verbose", - Usage: "enable verbose logging", + Usage: "Enable verbose logging", EnvVar: "DNSMASQ_VERBOSE", }, cli.BoolFlag{ Name: "syslog", - Usage: "enable syslog logging", + Usage: "Enable syslog logging", EnvVar: "DNSMASQ_SYSLOG", }, cli.BoolFlag{ Name: "multithreading", - Usage: "enable multithreading (num physical CPU cores)", + Usage: "Enable multithreading", EnvVar: "DNSMASQ_MULTITHREADING", }, } @@ -193,7 +188,6 @@ func main() { DnsAddr: listen, DefaultResolver: c.Bool("default-resolver"), Nameservers: nameservers, - Systemd: c.Bool("systemd"), SearchDomains: searchDomains, AppendDomain: c.Bool("append-search-domains"), Hostsfile: c.String("hostsfile"), diff --git a/server/config.go b/server/config.go index c55bf17..9aad8af 100644 --- a/server/config.go +++ b/server/config.go @@ -18,8 +18,6 @@ import ( type Config struct { // The ip:port go-dnsmasq should be listening on for incoming DNS requests. DnsAddr string `json:"dns_addr,omitempty"` - // bind to port(s) activated by systemd. If set to true, this overrides DnsAddr. - Systemd bool `json:"systemd,omitempty"` // Rewrite host's network config making go-dnsmasq the default resolver DefaultResolver bool `json:"default_resolver,omitempty"` // Domain to append to query names that are not FQDN diff --git a/server/forwarding.go b/server/forwarding.go index 952313f..78031ab 100644 --- a/server/forwarding.go +++ b/server/forwarding.go @@ -12,19 +12,18 @@ import ( "github.com/janeczku/go-dnsmasq/dns" ) -// ServeDNSForward forwards a request to a nameservers and returns the response. +// ServeDNSForward forwards a request to the nameserver and returns the response. func (s *server) ServeDNSForward(w dns.ResponseWriter, req *dns.Msg) *dns.Msg { if s.config.NoRec || len(s.config.Nameservers) == 0 { m := new(dns.Msg) m.SetReply(req) - m.SetRcode(req, dns.RcodeServerFailure) + m.SetRcode(req, dns.RcodeRefused) m.Authoritative = false m.RecursionAvailable = false if len(s.config.Nameservers) == 0 { - log.Debug("Can not forward query, no nameservers defined") - m.RecursionAvailable = true + log.Debug("Not forwarding query, no nameservers configured") } else { - m.RecursionAvailable = false + log.Debug("Not forwarding query, recursive mode disabled") } w.WriteMsg(m) @@ -33,15 +32,14 @@ func (s *server) ServeDNSForward(w dns.ResponseWriter, req *dns.Msg) *dns.Msg { name := req.Question[0].Name - if dns.CountLabel(name) < 2 || dns.CountLabel(name) < s.config.Ndots { - // Don't process single-label queries when searching is not enabled + if dns.CountLabel(name) < s.config.Ndots { if !s.config.AppendDomain || len(s.config.SearchDomains) == 0 { - log.Debugf("Can not forward query, name too short: `%s'", name) + log.Debugf("Not forwarding query, name too short: `%s'", name) m := new(dns.Msg) m.SetReply(req) - m.SetRcode(req, dns.RcodeServerFailure) + m.SetRcode(req, dns.RcodeRefused) m.Authoritative = false - m.RecursionAvailable = true + m.RecursionAvailable = false w.WriteMsg(m) return m } @@ -51,10 +49,10 @@ func (s *server) ServeDNSForward(w dns.ResponseWriter, req *dns.Msg) *dns.Msg { r *dns.Msg err error nsList []string - nsIndex int // nameserver list index - sdIndex int // search list index - sdName string // QNAME with search path - sdCname = new(dns.CNAME) // CNAME record returned when query resolved by searching + nsIndex int // Nameserver list index + sdIndex int // Search list index + sdName string // QNAME suffixed with search path + sdCname = new(dns.CNAME) // CNAME record we include in replies for queries resolved by searching ) tcp := isTCP(w) @@ -68,7 +66,7 @@ func (s *server) ServeDNSForward(w dns.ResponseWriter, req *dns.Msg) *dns.Msg { Redo: if dns.CountLabel(name) < 2 { - // always qualify single-label names + // Always qualify single-label names if !doingSearch && canSearch { doingSearch = true sdIndex = 0 @@ -101,7 +99,7 @@ Redo: } if err == nil { if canSearch { - // replicate libc's getaddrinfo.c search logic + // Replicate libc's getaddrinfo.c search logic switch { case r.Rcode == dns.RcodeSuccess && len(r.Answer) == 0 && !r.MsgHdr.Truncated: // NODATA !Truncated fallthrough @@ -109,12 +107,12 @@ Redo: fallthrough case r.Rcode == dns.RcodeServerFailure: // SERVFAIL if doingSearch && (sdIndex + 1) < len(s.config.SearchDomains) { - // continue searching + // Continue searching sdIndex++ goto Redo } if !doingSearch { - // start searching + // Start searching doingSearch = true sdIndex = 0 goto Redo @@ -123,7 +121,7 @@ Redo: } if r.Rcode == dns.RcodeServerFailure || r.Rcode == dns.RcodeRefused { - // continue with next available nameserver + // Continue with next available nameserver if (nsIndex + 1) < len(nsList) { nsIndex++ doingSearch = false @@ -131,7 +129,7 @@ Redo: } } - // We are done querying. Process the reply to return to the client. + // We are done querying. process the reply to return to the client. if doingSearch { // Insert cname record pointing name to name.searchdomain @@ -151,7 +149,7 @@ Redo: w.WriteMsg(r) return r } else { - log.Debugf("Error querying nameserver %s: %q", nsList[nsIndex], err) + log.Debugf("Error querying nameserver %s for qname %s: %q", nsList[nsIndex], name, err) // Got an error, this usually means the server did not respond // Continue with next available nameserver if (nsIndex + 1) < len(nsList) { @@ -162,7 +160,7 @@ Redo: } // If we got here it means forwarding failed - log.Errorf("Failure forwarding request %q", err) + log.Errorf("Failed to forward query for qname %s: %q", name, err) m := new(dns.Msg) m.SetReply(reqCopy) m.SetRcode(reqCopy, dns.RcodeServerFailure) @@ -181,7 +179,7 @@ func (s *server) ServeDNSReverse(w dns.ResponseWriter, req *dns.Msg) *dns.Msg { if records, err := s.PTRRecords(req.Question[0]); err == nil && len(records) > 0 { m.Answer = records if err := w.WriteMsg(m); err != nil { - log.Errorf("Failure returning reply %q", err) + log.Errorf("Failed to send reply: %q", err) } return m }