// domainsForRateLimiting transforms a list of FQDNs into a list of eTLD+1's // for the purpose of rate limiting. It also de-duplicates the output // domains. func domainsForRateLimiting(names []string) ([]string, error) { domainsMap := make(map[string]struct{}, len(names)) var domains []string for _, name := range names { eTLDPlusOne, err := publicsuffix.EffectiveTLDPlusOne(name) if err != nil { // The only possible errors are: // (1) publicsuffix.PublicSuffix is giving garbage // values // (2) the public suffix is the domain itself // // Assume (2). eTLDPlusOne = name } if _, ok := domainsMap[eTLDPlusOne]; !ok { domainsMap[eTLDPlusOne] = struct{}{} domains = append(domains, eTLDPlusOne) } } return domains, nil }
func main() { cacheFile := flag.String("ctFile", "", "") nameFile := flag.String("nameFile", "", "") normalResolver := flag.String("normalResolver", "127.0.0.1:53", "") torResolver := flag.String("torResolver", "127.0.0.1:9053", "") workers := flag.Int("workers", 1, "") flag.Parse() if *cacheFile == "" && *nameFile == "" { fmt.Println("Either --ctFile or --nameFile is required") os.Exit(1) } t := tester{ workers: *workers, client: &dns.Client{DialTimeout: dnsTimeout, ReadTimeout: dnsTimeout, Net: "tcp"}, normalResolver: *normalResolver, torResolver: *torResolver, } if *cacheFile != "" { ctEntries, err := ctCommon.LoadCacheFile(*cacheFile) if err != nil { fmt.Printf("Failed to load CT cache file: %s\n", err) os.Exit(1) } names := make(map[string]struct{}) mu := new(sync.Mutex) ctEntries.Map(func(ent *ct.EntryAndPosition, err error) { if err != nil || ent.Entry.Type != ct.X509Entry { return } cert, _, err := ctCommon.ParseAndFilter(ent.Entry.X509Cert, nil) if err != nil { return } for _, name := range cert.DNSNames { eTLD, err := publicsuffix.EffectiveTLDPlusOne(name) if err != nil { continue } mu.Lock() if _, present := names[eTLD]; !present { names[eTLD] = struct{}{} } mu.Unlock() } }) numNames := len(names) t.names = make(chan string, numNames) t.results = make(chan *result, numNames) for name := range names { t.names <- name } } if *nameFile != "" { data, err := ioutil.ReadFile(*nameFile) if err != nil { fmt.Printf("Failed to read name file: %s\n", err) os.Exit(1) } names := strings.Split(string(data), "\n") numNames := len(names) t.names = make(chan string, numNames) t.results = make(chan *result, numNames) for _, name := range names { t.names <- name } } close(t.names) t.run() t.dump() }