name5/queries.go

77 lines
1.8 KiB
Go

package Name5
import (
"time"
"github.com/miekg/dns"
"github.com/rs/zerolog/log"
"github.com/yunginnanet/Rate5"
)
// TODO: benchmarks
// TODO: better ratelimiting logic
// global dummy type for rater
type resolveSlower struct {
key string
}
func (rs *resolveSlower) UniqueKey() string {
return rs.key
}
var dnsRater *rate5.Limiter
/*
SmuggleError crafts a custom DNS answer to include our error message.
This allows the function to only have one return, thus simplifying our pipeline. (maybe)
*/
func SmuggleError(err error) *dns.Msg {
dnserr := new(dns.Msg)
dnserr.Answer = make([]dns.RR, 1)
dnserr.Answer[0] = new(dns.NULL)
dnserr.Answer[0].(*dns.NULL).Data = err.Error()
return dnserr
}
func query(domain string, qtype uint16) *dns.Msg {
if dnsRater.Check(&resolveSlower{key: "yeet"}) {
time.Sleep(10 * time.Millisecond)
}
domain = dns.Fqdn(domain)
m1 := new(dns.Msg)
m1.Id = dns.Id()
m1.RecursionDesired = true
m1.Question = make([]dns.Question, 1)
m1.Question[0] = dns.Question{Name: domain, Qtype: qtype, Qclass: dns.ClassINET}
lookup := &dns.Client{
Timeout: time.Duration(6) * time.Second,
SingleInflight: true,
}
in, _, err := lookup.Exchange(m1, "127.0.0.1:53")
if err != nil {
log.Error().Err(err).Msg("query")
resp := SmuggleError(err)
resp.Question = append(resp.Question, m1.Question[0])
return resp
}
in.Answer = dns.Dedup(in.Answer, nil)
in.Ns = dns.Dedup(in.Ns, nil)
in.Extra = dns.Dedup(in.Extra, nil)
return in
}
// Query4 requests an A record answer
func Query4(domain string) *dns.Msg {
return query(domain, 1)
}
// Query6 requests an AAAA record answer
func Query6(domain string) *dns.Msg {
return query(domain, 28)
}
// QueryPTR retrievs reverse DNS records
func QueryPTR(ip string) *dns.Msg {
return query(ip, 12)
}