zabov/dns_client.go

124 lines
2.5 KiB
Go
Raw Normal View History

2020-10-08 16:14:07 -04:00
package main
import (
"fmt"
"log"
2020-10-08 16:14:07 -04:00
"time"
"math/rand"
"strings"
"github.com/miekg/dns"
)
//ForwardQuery forwards the query to the upstream server
//first server to answer wins
//accepts config name to select the UP DNS source list
func ForwardQuery(query *dns.Msg, config string, nocache bool) *dns.Msg {
if ZabovDebug {
log.Println("ForwardQuery: nocache", nocache)
}
2020-10-08 16:14:07 -04:00
go incrementStats("ForwardQueries", 1)
r := new(dns.Msg)
r.SetReply(query)
r.Authoritative = true
fqdn := strings.TrimRight(query.Question[0].Name, ".")
lfqdn := fmt.Sprintf("%d", query.Question[0].Qtype) + "." + fqdn
if !nocache {
if cached := GetDomainFromCache(lfqdn); cached != nil {
go incrementStats("CacheHit", 1)
Rcode := cached.MsgHdr.Rcode
cached.SetReply(query)
cached.MsgHdr.Rcode = Rcode
cached.Authoritative = true
if ZabovDebug {
log.Println("ForwardQuery: CacheHit")
}
cached.Compress = true
return cached
}
2020-10-08 16:14:07 -04:00
}
c := new(dns.Client)
c.ReadTimeout = 500 * time.Millisecond
c.WriteTimeout = 500 * time.Millisecond
for {
// round robin with retry
// local responder should always be available also if no internet connection
if !NetworkUp && localresponderConfigName != config {
2020-10-08 16:14:07 -04:00
time.Sleep(10 * time.Second)
go incrementStats("Network Problems ", 1)
continue
}
d := oneTimeDNS(config)
2020-10-08 16:14:07 -04:00
in, _, err := c.Exchange(query, d)
if err != nil {
fmt.Printf("Problem with DNS %s : %s\n", d, err.Error())
go incrementStats("DNS Problems "+d, 1)
continue
} else {
go incrementStats(d, 1)
Rcode := in.MsgHdr.Rcode
2020-10-08 16:14:07 -04:00
in.SetReply(query)
in.MsgHdr.Rcode = Rcode
2020-10-08 16:14:07 -04:00
in.Authoritative = true
in.Compress = true
2020-10-08 16:14:07 -04:00
go DomainCache(lfqdn, in)
if ZabovDebug {
log.Println("ForwardQuery: OK!")
}
2020-10-08 16:14:07 -04:00
return in
}
}
}
func init() {
fmt.Println("DNS client engine starting")
NetworkUp = checkNetworkUp()
if NetworkUp {
fmt.Println("[OK]: Network is UP")
} else {
fmt.Println("[KO] Network is DOWN: system will check again in 2 minutes")
}
}
func oneTimeDNS(config string) (dns string) {
2020-10-08 16:14:07 -04:00
rand.Seed(time.Now().Unix())
upl := ZabovConfigs[config].ZabovDNSArray
2020-10-08 16:14:07 -04:00
if len(upl) < 1 {
if len(ZabovLocalResponder) > 0 {
fmt.Println("No DNS defined, fallback to local responder:", ZabovLocalResponder)
return ZabovLocalResponder
}
2020-10-08 16:14:07 -04:00
fmt.Println("No DNS defined, using default 127.0.0.53:53. Hope it works!")
return "127.0.0.53:53"
}
n := rand.Intn(128*len(upl)) % len(upl)
dns = upl[n]
return
}