Skip to content

Commit

Permalink
MInor fixes:
Browse files Browse the repository at this point in the history
* Correct spelling in command line help strings
* Make error messages more informative
* When forwarding is prohibited return REFUSED instead of SERVFAIL
  • Loading branch information
Jan Broer committed Mar 5, 2016
1 parent 99d111a commit 561a386
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 58 deletions.
28 changes: 15 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -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.

Expand Down Expand Up @@ -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 | | |
Expand Down Expand Up @@ -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.
34 changes: 14 additions & 20 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (
)

// var Version string
const Version = "1.0.0"
const Version = "1.0.1"

var (
nameservers = []string{}
Expand All @@ -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",
},
}
Expand Down Expand Up @@ -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"),
Expand Down
2 changes: 0 additions & 2 deletions server/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
44 changes: 21 additions & 23 deletions server/forwarding.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
}
Expand All @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -101,20 +99,20 @@ 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
case r.Rcode == dns.RcodeNameError: // NXDOMAIN
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
Expand All @@ -123,15 +121,15 @@ 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
goto 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
Expand All @@ -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) {
Expand All @@ -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)
Expand All @@ -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
}
Expand Down

0 comments on commit 561a386

Please sign in to comment.