Skip to content

Commit

Permalink
Merge branch 'master' into minimal
Browse files Browse the repository at this point in the history
  • Loading branch information
Jan Broer committed Oct 19, 2015
1 parent b997a2d commit cf2d934
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 45 deletions.
49 changes: 27 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# go-dnsmasq
*Version 0.9.3*
*Version 0.9.7*

go-dnsmasq is a lightweight (1.4 MB) caching DNS forwarder/proxy optimized for running in Docker containers.
go-dnsmasq is a lightweight (1.2 MB) caching DNS forwarder/proxy with minimal filesystem and runtime overhead. It was designed but is not limited to be run in Docker containers.

### Notable features (all configurable)

Expand All @@ -23,27 +23,32 @@ NAME:

USAGE:
go-dnsmasq [global options] command [command options] [arguments...]


VERSION:
0.9.7

COMMANDS:
help, h Shows a list of commands or help for one command

help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--listen, -l "127.0.0.1:53" listen address: ‘host[:port]‘ [$DNSMASQ_LISTEN]
--default-resolver, -d make go-dnsmasq the default name server (updates /etc/resolv.conf) [$DNSMASQ_DEFAULT]
--nameservers, -n comma-separated list of name servers: ‘host[:port]‘ [$DNSMASQ_SERVERS]
--stubzones, -z domains to resolve using a specific nameserver: ‘domain[,domain]/host[:port]‘ [$DNSMASQ_STUB]
--hostsfile, -f full path to hostsfile (e.g. ‘/etc/hosts‘) [$DNSMASQ_HOSTSFILE]
--hostsfile-poll, -p "0" how frequently to poll hostsfile (in seconds, ‘0‘ to disable) [$DNSMASQ_POLL]
--search-domains, -s specify SEARCH domains taking precedence over /etc/resolv.conf: ‘fqdn[,fqdn]‘ [$DNSMASQ_SEARCH]
--append-search-domains, -a enable suffixing single-label queries with SEARCH domains [$DNSMASQ_APPEND]
--rcache, -r "0" capacity of the response cache (‘0‘ to disable caching) [$DNSMASQ_RCACHE]
--rcache-ttl "60" TTL of entries in the response cache [$DNSMASQ_RCACHE_TTL]
--no-rec disable recursion [$DNSMASQ_NOREC]
--round-robin enable round robin of A/AAAA replies [$DNSMASQ_RR]
--systemd bind to socket(s) activated by systemd (ignores --listen) [$DNSMASQ_SYSTEMD]
--verbose enable verbose logging [$DNSMASQ_VERBOSE]
--help, -h show help
--version, -v print the version
--listen, -l "127.0.0.1:53" listen address: ‘host[:port]‘ [$DNSMASQ_LISTEN]
--default-resolver, -d make go-dnsmasq the local primary nameserver (updates /etc/resolv.conf) [$DNSMASQ_DEFAULT]
--nameservers, -n comma-separated list of name servers: ‘host[:port]‘ [$DNSMASQ_SERVERS]
--stubzones, -z domains to resolve using a specific nameserver: ‘fqdn[,fqdn]/host[:port]‘ [$DNSMASQ_STUB]
--hostsfile, -f full path to hostsfile (e.g. ‘/etc/hosts‘) [$DNSMASQ_HOSTSFILE]
--hostsfile-poll, -p "0" how frequently to poll hostsfile (in seconds, ‘0‘ to disable) [$DNSMASQ_POLL]
--search-domains, -s specify search domains taking precedence over resolv.conf: ‘fqdn[,fqdn]‘ [$DNSMASQ_SEARCH]
--append-search-domains, -a enable suffixing single-label queries with SEARCH domains [$DNSMASQ_APPEND]
--rcache, -r "0" capacity of the response cache (‘0‘ to disable caching) [$DNSMASQ_RCACHE]
--rcache-ttl "60" TTL of entries in the response cache [$DNSMASQ_RCACHE_TTL]
--no-rec disable recursion [$DNSMASQ_NOREC]
--round-robin enable round robin of A/AAAA replies [$DNSMASQ_RR]
--systemd bind to socket(s) activated by systemd (ignores --listen) [$DNSMASQ_SYSTEMD]
--verbose enable verbose logging [$DNSMASQ_VERBOSE]
--syslog enable syslog logging [$DNSMASQ_SYSLOG]
--multithreading enable multithreading (num physical CPU cores) [$DNSMASQ_MULTITHREADING]
--help, -h show help
--version, -v print the version
```

### Environment Variables
Expand All @@ -56,7 +61,7 @@ See above (the names inside the brackets).

Download the binary for your OS from the [releases page](https://github.com/janeczku/go-dnsmasq/releases/latest).

go-dnsmasq is available in two versions. The minimal binary (`go-dnsmasq-min`) has a lower memory footprint but doesn't include caching, stats reporting and systemd support.
go-dnsmasq is available in two versions. The minimal version (`go-dnsmasq-min`) has a lower memory footprint but doesn't have caching, stats reporting and systemd support.

```sh
sudo ./go-dnsmasq [options]
Expand Down
55 changes: 32 additions & 23 deletions server/forwarding.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,11 @@ func (s *server) ServeDNSForward(w dns.ResponseWriter, req *dns.Msg) *dns.Msg {
return m
}

reqOrig := req.Copy()
name := req.Question[0].Name
doingSearch := false
searchCname := new(dns.CNAME)
var nameFqdn string

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) < 2 && !s.config.AppendDomain {
if !s.config.AppendDomain || len(s.config.SearchDomains) == 0 {
log.Debugf("Can not forward query, name too short: `%s'", name)
m := new(dns.Msg)
m.SetReply(req)
Expand All @@ -51,24 +47,37 @@ func (s *server) ServeDNSForward(w dns.ResponseWriter, req *dns.Msg) *dns.Msg {
}
}

tcp := isTCP(w)

var (
r *dns.Msg
err error
nsIndex int // Primary server (first in list) is always queried first (libc logic)
sdIndex int
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
)

tcp := isTCP(w)
reqCopy := req.Copy()
canSearch := false
doingSearch := false

if s.config.AppendDomain && len(s.config.SearchDomains) > 0 {
canSearch = true
}

Redo:
if !doingSearch && dns.CountLabel(name) < 2 { // always qualify single-label names before forwarding
doingSearch = true
if dns.CountLabel(name) < 2 {
// always qualify single-label names
if !doingSearch && canSearch {
doingSearch = true
sdIndex = 0
}
}
if doingSearch {
nameFqdn = strings.ToLower(appendDomain(name, s.config.SearchDomains[sdIndex]))
searchCname.Hdr = dns.RR_Header{Name: name, Rrtype: dns.TypeCNAME, Class: dns.ClassINET, Ttl: 360}
searchCname.Target = nameFqdn
req.Question[0] = dns.Question{nameFqdn, req.Question[0].Qtype, req.Question[0].Qclass}
sdName = strings.ToLower(appendDomain(name, s.config.SearchDomains[sdIndex]))
sdCname.Hdr = dns.RR_Header{Name: name, Rrtype: dns.TypeCNAME, Class: dns.ClassINET, Ttl: 360}
sdCname.Target = sdName
req.Question[0] = dns.Question{sdName, req.Question[0].Qtype, req.Question[0].Qclass}
}

switch tcp {
Expand All @@ -78,7 +87,7 @@ Redo:
r, _, err = s.dnsTCPclient.Exchange(req, s.config.Nameservers[nsIndex])
}
if err == nil {
if s.config.AppendDomain { // searching is enabled
if canSearch {
// replicate libc's getaddrinfo.c search logic
switch {
case r.Rcode == dns.RcodeSuccess && len(r.Answer) == 0: // NODATA
Expand All @@ -94,6 +103,7 @@ Redo:
if !doingSearch {
// start searching
doingSearch = true
sdIndex = 0
goto Redo
}
}
Expand All @@ -104,24 +114,23 @@ Redo:
if (nsIndex + 1) < len(s.config.Nameservers) {
nsIndex++
doingSearch = false
sdIndex = 0
goto Redo
}
}

// We are done querying. Process the reply to return to the client.

if doingSearch {
// Insert cname record pointing queryname to queryname.searchdomain
// Insert cname record pointing name to name.searchdomain
if len(r.Answer) > 0 {
answers := []dns.RR{searchCname}
answers := []dns.RR{sdCname}
for _, rr := range r.Answer {
answers = append(answers, rr)
}
r.Answer = answers
}
// Restore original question
r.Question[0] = reqOrig.Question[0]
r.Question[0] = reqCopy.Question[0]
}

r.Compress = true
Expand All @@ -135,15 +144,15 @@ Redo:
if (nsIndex + 1) < len(s.config.Nameservers) {
nsIndex++
doingSearch = false
sdIndex = 0
goto Redo
}
}

// If we got here it means forwarding failed
log.Errorf("Failure forwarding request %q", err)
m := new(dns.Msg)
m.SetReply(reqOrig)
m.SetRcode(reqOrig, dns.RcodeServerFailure)
m.SetReply(reqCopy)
m.SetRcode(reqCopy, dns.RcodeServerFailure)
w.WriteMsg(m)
return m
}
Expand Down

0 comments on commit cf2d934

Please sign in to comment.