patdown/cmd/patdown/main.go

136 lines
2.8 KiB
Go

package main
import (
"flag"
"fmt"
"time"
"patdown/common"
"github.com/miekg/dns"
)
type multiflag []string
type Pair struct {
Nameserver string
Domain string
}
func (m *multiflag) String() string {
return "irc.supernets.org #superbowl"
}
func (m *multiflag) Set(value string) error {
*m = append(*m, value)
return nil
}
var (
domain = flag.String("t", "", "domain to query")
workers = flag.Int("c", 100, "number of workers")
delay = flag.Int("s", 100, "delay (sleep) between queries in milliseconds")
nameserver multiflag
)
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{dns.Fqdn(domain), reqtype, dns.ClassINET}
return msg
}
func query(q <-chan Pair, tracker chan<- interface{}) {
for pair := range q {
msg := message(pair.Domain, dns.TypeA, false)
// fmt.Println("Querying ", pair.Domain, " on ", pair.Nameserver)
in, err := dns.Exchange(msg, pair.Nameserver+":53")
if err != nil {
common.Error(err.Error())
continue
}
if len(in.Answer) > 0 {
fmt.Printf("[%s] associated domain %s found on %s\n", common.Vendors[common.Domains[pair.Domain]], pair.Domain, pair.Nameserver)
}
time.Sleep(time.Duration(*delay) * time.Millisecond)
}
tracker <- 1337
}
func testns(ns string) error {
msg := message("supernets.org", dns.TypeA, false)
_, err := dns.Exchange(msg, ns+":53")
if err != nil {
return err
}
return nil
}
func main() {
flag.Var(&nameserver, "n", "nameserver to query")
flag.Usage = common.Usage
flag.Parse()
var nameservers []string
pairs := make(chan Pair)
tracker := make(chan interface{})
common.Banner()
if *domain != "" {
// query domain for nameservers
nsmsg := message(*domain, dns.TypeNS, true)
in, err := dns.Exchange(nsmsg, "1.1.1.1:53")
if err != nil {
panic(err)
}
for _, ans := range in.Answer {
ns, ok := ans.(*dns.NS)
if ok {
nameservers = append(nameservers, ns.Ns)
}
}
fmt.Println(nameservers)
} else if len(nameserver) > 0 {
for _, ns := range nameserver {
nameservers = append(nameservers, ns)
}
} else {
// print usage
}
common.Info("aggregating nameservers...")
for i, ns := range nameservers {
if err := testns(ns); err != nil {
common.Error("nameserver " + ns + " is not responding")
nameservers = append(nameservers[:i], nameservers[i+1:]...)
}
}
common.Info(fmt.Sprintf("snooping EDR domains from %d resolvers...", len(nameservers)))
go func() {
for i := 0; i < *workers; i++ {
query(pairs, tracker)
}
}()
for _, ns := range nameservers {
for k, _ := range common.Domains {
pairs <- Pair{Nameserver: ns, Domain: k}
}
}
close(pairs)
for x := 0; x < *workers; x++ {
<-tracker
}
}