package main import ( "bufio" "context" "flag" "fmt" "math/rand" "net" "os" "strconv" "strings" "sync" "time" ) var dnsServers []string func loadDNSServersFromFile(filePath string) error { file, err := os.Open(filePath) if err != nil { return err } defer file.Close() scanner := bufio.NewScanner(file) for scanner.Scan() { server := scanner.Text() // Check if the server contains a port if strings.Contains(server, ":") { host, port, err := net.SplitHostPort(server) if err != nil { return fmt.Errorf("invalid IP:port format for %s", server) } if net.ParseIP(host) == nil { return fmt.Errorf("invalid IP address in %s", server) } if _, err := strconv.Atoi(port); err != nil { return fmt.Errorf("invalid port in %s", server) } } else { if net.ParseIP(server) == nil { return fmt.Errorf("invalid IP address %s", server) } server += ":53" // Default to port 53 if not specified } dnsServers = append(dnsServers, server) } return scanner.Err() } func reverseDNSLookup(ip string, server string) string { ctx := context.Background() resolver := &net.Resolver{ PreferGo: true, Dial: func(ctx context.Context, network, address string) (net.Conn, error) { d := net.Dialer{} return d.DialContext(ctx, network, server) }, } names, err := resolver.LookupAddr(ctx, ip) if err != nil { return fmt.Sprintf("%s | %s | Error: %s", time.Now().Format("03:04:05 PM"), server, err) } if len(names) == 0 { return fmt.Sprintf("%s | %s | No PTR records", time.Now().Format("03:04:05 PM"), server) } return fmt.Sprintf("%s | %s | %s", time.Now().Format("03:04:05 PM"), server, names[0]) } func worker(cidr *net.IPNet, resultsChan chan string) { for ip := make(net.IP, len(cidr.IP)); copy(ip, cidr.IP) != 0; incrementIP(ip) { if !cidr.Contains(ip) { break } randomServer := dnsServers[rand.Intn(len(dnsServers))] result := reverseDNSLookup(ip.String(), randomServer) resultsChan <- result } } func splitCIDR(cidr string, parts int) ([]*net.IPNet, error) { ip, ipNet, err := net.ParseCIDR(cidr) if err != nil { return nil, err } maskSize, _ := ipNet.Mask.Size() newMaskSize := maskSize for ; (1 << uint(newMaskSize-maskSize)) < parts; newMaskSize++ { if newMaskSize > 32 { return nil, fmt.Errorf("too many parts; cannot split further") } } var subnets []*net.IPNet for i := 0; i < parts; i++ { subnets = append(subnets, &net.IPNet{ IP: ip, Mask: net.CIDRMask(newMaskSize, 32), }) incrementIPBy(ip, 1<= 0; j-- { ip[j]++ if ip[j] > 0 { break } } } func incrementIPBy(ip net.IP, count int) { for count > 0 { incrementIP(ip) count-- } }