patdown/common/net.go

141 lines
3.8 KiB
Go

package common
import (
"fmt"
"time"
"github.com/miekg/dns"
)
type Query struct {
Nameserver string
Vendor string
DomainPair Pair
}
type Nameserver struct {
Nameserver string
NonRA bool
Recursive bool
}
func message(domain string, reqtype uint16, ra bool) *dns.Msg {
msg := new(dns.Msg)
msg.Id = dns.Id()
msg.RecursionDesired = ra
msg.Question = make([]dns.Question, 1)
msg.Question[0] = dns.Question{
Name: dns.Fqdn(domain),
Qtype: reqtype,
Qclass: dns.ClassINET,
}
return msg
}
func ParseNS(nameservers []string) []Nameserver {
var valid []Nameserver
msg := message("cloudflare.com", dns.TypeA, false)
for _, ns := range nameservers {
nonra, ra := false, false
in, err := dns.Exchange(msg, ns+":53")
if err != nil {
Error(fmt.Sprintf("nameserver %s%s%s is not responding to the trial query", ColorGray, ns[0:len(ns)-1], ColorReset))
continue
}
if in.Rcode == dns.RcodeRefused {
Warn(fmt.Sprintf("nameserver %s%s%s refused the trial non-recursive query", ColorGray, ns[0:len(ns)-1], ColorReset))
} else {
Success(fmt.Sprintf("nameserver %s%s%s allows non-recursive queries", ColorGray, ns[0:len(ns)-1], ColorReset))
nonra = true
}
if in.RecursionAvailable {
Success(fmt.Sprintf("nameserver %s%s%s allows recursion", ColorGray, ns[0:len(ns)-1], ColorReset))
ra = true
} else {
Warn(fmt.Sprintf("nameserver %s%s%s does not allow recursion", ColorGray, ns[0:len(ns)-1], ColorReset))
}
valid = append(valid, Nameserver{Nameserver: ns, NonRA: nonra, Recursive: ra})
}
return valid
}
func NeutralReq() bool {
msg := message("supernets.org", dns.TypeA, true)
in, err := dns.Exchange(msg, "1.1.1.1:53")
if err != nil {
return false
}
if len(in.Answer) > 0 {
return true
}
return false
}
func PullNS(d string) []string {
nsmsg := message(d, dns.TypeNS, true)
in, err := dns.Exchange(nsmsg, "1.1.1.1:53")
if err != nil {
Fatal("unable to retrieve nameservers for " + d)
}
nameservers := []string{}
for _, ans := range in.Answer {
ns, ok := ans.(*dns.NS)
if ok {
nameservers = append(nameservers, ns.Ns)
}
}
return nameservers
}
func RunQuery(q <-chan Query, tracker chan<- interface{}, delay int) {
for qdata := range q {
if Params.Verbose {
Info(fmt.Sprintf("querying %s on %s", qdata.DomainPair.Domain, qdata.Nameserver[0:len(qdata.Nameserver)-1]))
}
msg := message(qdata.DomainPair.Domain, dns.TypeA, false)
in, err := dns.Exchange(msg, qdata.Nameserver+":53")
if err != nil {
Error(err.Error())
continue
}
if len(in.Answer) > 0 {
Success(fmt.Sprintf("[%s] associated domain %s%s%s found on %s%s%s",
qdata.Vendor, ColorRed, qdata.DomainPair.Domain, ColorReset, ColorRed, qdata.Nameserver[0:len(qdata.Nameserver)-1], ColorReset))
}
time.Sleep(time.Duration(delay) * time.Millisecond)
}
tracker <- 1337
}
func RunQueryRA(q <-chan Query, tracker chan<- interface{}, delay int) {
for qdata := range q {
if Params.Verbose {
Info(fmt.Sprintf("recursively querying %s on %s", qdata.DomainPair.Domain, qdata.Nameserver[0:len(qdata.Nameserver)-1]))
}
for x := 0; x < 2; x++ {
msg := message(qdata.DomainPair.Domain, dns.TypeA, true)
in, err := dns.Exchange(msg, qdata.Nameserver+":53")
if err != nil {
Error("hiccup on " + qdata.Nameserver[0:len(qdata.Nameserver)-1] + " while querying " + qdata.DomainPair.Domain)
time.Sleep(2 * time.Second)
continue
}
if len(in.Answer) > 0 {
if in.Answer[0].Header().Ttl <= qdata.DomainPair.TTL-4 {
Success(fmt.Sprintf("[%s] associated domain %s%s%s found on %s%s%s with decremented TTL of %s%d%s",
qdata.Vendor, ColorRed, qdata.DomainPair.Domain, ColorReset, ColorRed, qdata.Nameserver[0:len(qdata.Nameserver)-1], ColorReset, ColorGreen, in.Answer[0].Header().Ttl, ColorReset))
}
}
break
}
time.Sleep(time.Duration(delay) * time.Millisecond)
}
tracker <- 1337
}