You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
4.5 KiB
171 lines
4.5 KiB
package main |
|
|
|
import ( |
|
"log" |
|
// "sync" |
|
|
|
"github.com/miekg/dns" |
|
) |
|
|
|
// updateDNS updates the current slices of dns.RR so incoming requests get a |
|
// fast answer |
|
func updateDNS(s *dnsseeder) { |
|
|
|
var rr4std, rr4non, rr6std, rr6non []dns.RR |
|
|
|
s.mtx.RLock() |
|
|
|
// loop over each dns recprd type we need |
|
for t := range []int{dnsV4Std, dnsV4Non, dnsV6Std, dnsV6Non} { |
|
// FIXME above needs to be convertwd into one scan of theList if possible |
|
|
|
numRR := 0 |
|
|
|
for _, nd := range s.theList { |
|
// when we reach max exit |
|
if numRR >= 25 { |
|
break |
|
} |
|
|
|
if nd.status != statusCG { |
|
continue |
|
} |
|
|
|
if t == dnsV4Std || t == dnsV4Non { |
|
if t == dnsV4Std && nd.dnsType == dnsV4Std { |
|
r := new(dns.A) |
|
r.Hdr = dns.RR_Header{Name: s.dnsHost + ".", Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: s.ttl} |
|
r.A = nd.na.IP |
|
rr4std = append(rr4std, r) |
|
numRR++ |
|
} |
|
|
|
// if the node is using a non standard port then add the encoded port info to DNS |
|
if t == dnsV4Non && nd.dnsType == dnsV4Non { |
|
r := new(dns.A) |
|
r.Hdr = dns.RR_Header{Name: "nonstd." + s.dnsHost + ".", Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: s.ttl} |
|
r.A = nd.na.IP |
|
rr4non = append(rr4non, r) |
|
numRR++ |
|
r = new(dns.A) |
|
r.Hdr = dns.RR_Header{Name: "nonstd." + s.dnsHost + ".", Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: s.ttl} |
|
r.A = nd.nonstdIP |
|
rr4non = append(rr4non, r) |
|
numRR++ |
|
} |
|
} |
|
if t == dnsV6Std || t == dnsV6Non { |
|
if t == dnsV6Std && nd.dnsType == dnsV6Std { |
|
r := new(dns.AAAA) |
|
r.Hdr = dns.RR_Header{Name: s.dnsHost + ".", Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: s.ttl} |
|
r.AAAA = nd.na.IP |
|
rr6std = append(rr6std, r) |
|
numRR++ |
|
} |
|
// if the node is using a non standard port then add the encoded port info to DNS |
|
if t == dnsV6Non && nd.dnsType == dnsV6Non { |
|
r := new(dns.AAAA) |
|
r.Hdr = dns.RR_Header{Name: "nonstd." + s.dnsHost + ".", Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: s.ttl} |
|
r.AAAA = nd.na.IP |
|
rr6non = append(rr6non, r) |
|
numRR++ |
|
r = new(dns.AAAA) |
|
r.Hdr = dns.RR_Header{Name: "nonstd." + s.dnsHost + ".", Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: s.ttl} |
|
r.AAAA = nd.nonstdIP |
|
rr6non = append(rr6non, r) |
|
numRR++ |
|
} |
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
s.mtx.RUnlock() |
|
|
|
config.dnsmtx.Lock() |
|
|
|
// update the map holding the details for this seeder |
|
for t := range []int{dnsV4Std, dnsV4Non, dnsV6Std, dnsV6Non} { |
|
switch t { |
|
case dnsV4Std: |
|
config.dns[s.dnsHost+".A"] = rr4std |
|
case dnsV4Non: |
|
config.dns["nonstd."+s.dnsHost+".A"] = rr4non |
|
case dnsV6Std: |
|
config.dns[s.dnsHost+".AAAA"] = rr6std |
|
case dnsV6Non: |
|
config.dns["nonstd."+s.dnsHost+".AAAA"] = rr6non |
|
} |
|
} |
|
|
|
config.dnsmtx.Unlock() |
|
|
|
if config.stats { |
|
s.counts.mtx.RLock() |
|
log.Printf("%s - DNS available: v4std: %v v4non: %v v6std: %v v6non: %v\n", s.name, len(rr4std), len(rr4non), len(rr6std), len(rr6non)) |
|
log.Printf("%s - DNS counts: v4std: %v v4non: %v v6std: %v v6non: %v total: %v\n", |
|
s.name, |
|
s.counts.DNSCounts[dnsV4Std], |
|
s.counts.DNSCounts[dnsV4Non], |
|
s.counts.DNSCounts[dnsV6Std], |
|
s.counts.DNSCounts[dnsV6Non], |
|
s.counts.DNSCounts[dnsV4Std]+s.counts.DNSCounts[dnsV4Non]+s.counts.DNSCounts[dnsV6Std]+s.counts.DNSCounts[dnsV6Non]) |
|
|
|
s.counts.mtx.RUnlock() |
|
|
|
} |
|
} |
|
|
|
// handleDNS processes a DNS request from remote client and returns |
|
// a list of current ip addresses that the crawlers consider current. |
|
func handleDNS(w dns.ResponseWriter, r *dns.Msg) { |
|
|
|
m := &dns.Msg{MsgHdr: dns.MsgHdr{ |
|
Authoritative: true, |
|
RecursionAvailable: false, |
|
}} |
|
m.SetReply(r) |
|
|
|
var qtype string |
|
|
|
switch r.Question[0].Qtype { |
|
case dns.TypeA: |
|
qtype = "A" |
|
case dns.TypeAAAA: |
|
qtype = "AAAA" |
|
case dns.TypeTXT: |
|
qtype = "TXT" |
|
case dns.TypeMX: |
|
qtype = "MX" |
|
case dns.TypeNS: |
|
qtype = "NS" |
|
default: |
|
qtype = "UNKNOWN" |
|
} |
|
|
|
config.dnsmtx.RLock() |
|
// if the dns map does not have a key for the request it will return an empty slice |
|
m.Answer = config.dns[r.Question[0].Name+qtype] |
|
config.dnsmtx.RUnlock() |
|
|
|
w.WriteMsg(m) |
|
|
|
if config.debug { |
|
log.Printf("debug - DNS response Type: standard To IP: %s Query Type: %s\n", w.RemoteAddr().String(), qtype) |
|
} |
|
// update the stats in a goroutine |
|
go updateDNSCounts(r.Question[0].Name, qtype) |
|
} |
|
|
|
// serve starts the requested DNS server listening on the requested port |
|
func serve(net, port string) { |
|
server := &dns.Server{Addr: ":" + port, Net: net, TsigSecret: nil} |
|
if err := server.ListenAndServe(); err != nil { |
|
log.Printf("Failed to setup the "+net+" server: %v\n", err) |
|
} |
|
} |
|
|
|
/* |
|
|
|
*/
|
|
|