-
-
Save nirohfeld/c596898673ead369cb8992d97a1c764e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"flag" | |
"fmt" | |
"net" | |
"os" | |
"strings" | |
"sync" | |
"time" | |
"github.com/cheggaaa/pb/v3" | |
) | |
func performLookup(ip net.IP, results chan<- string, bar *pb.ProgressBar, retryCount int) { | |
var err error | |
var names []string | |
for i := 0; i < retryCount; i++ { | |
names, err = net.LookupAddr(ip.String()) | |
if err == nil { | |
break | |
} | |
// Reduced sleep for retry to make it faster | |
time.Sleep(10 * time.Millisecond) // Shorter delay between retries | |
} | |
if err == nil && len(names) > 0 { | |
fmt.Println(ip, names[0]) | |
results <- fmt.Sprintf("%s -> %s", ip, names[0]) | |
} | |
bar.Increment() | |
} | |
func main() { | |
var inputFlag string | |
flag.StringVar(&inputFlag, "subnet", "", "Input to scan, CIDR notation (e.g., 10.5.0.0/24) or wildcard (e.g., 10.5.0.*)") | |
flag.Parse() | |
if inputFlag == "" { | |
fmt.Println("Usage: ./dnscan -subnet <CIDR or Wildcard>") | |
os.Exit(1) | |
} | |
ips, err := parseInput(inputFlag) | |
if err != nil { | |
fmt.Printf("Error processing subnet: %v\n", err) | |
os.Exit(1) | |
} | |
results := make(chan string) | |
bar := pb.StartNew(len(ips)) | |
retryCount := 2 | |
var wg sync.WaitGroup | |
rateLimit := time.Tick(1 * time.Millisecond) | |
for _, ip := range ips { | |
wg.Add(1) | |
<-rateLimit | |
go func(ip net.IP) { | |
defer wg.Done() | |
performLookup(ip, results, bar, retryCount) | |
}(ip) | |
} | |
go func() { | |
wg.Wait() | |
close(results) | |
bar.Finish() | |
}() | |
for r := range results { | |
fmt.Println(r) | |
} | |
} | |
func parseInput(input string) ([]net.IP, error) { | |
if strings.Contains(input, "*") { | |
// Convert wildcard to CIDR | |
cidrs, err := wildcardToCIDRs(input) | |
if err != nil { | |
return nil, err | |
} | |
var ips []net.IP | |
for _, cidr := range cidrs { | |
_, ipnet, _ := net.ParseCIDR(cidr) | |
ips = append(ips, generateIPsFromCIDR(ipnet)...) | |
} | |
return ips, nil | |
} else { | |
_, ipnet, err := net.ParseCIDR(input) | |
if err != nil { | |
return nil, fmt.Errorf("invalid input: %v", err) | |
} | |
return generateIPsFromCIDR(ipnet), nil | |
} | |
} | |
func wildcardToCIDRs(wildcard string) ([]string, error) { | |
parts := strings.Split(wildcard, ".") | |
if len(parts) != 4 { | |
return nil, fmt.Errorf("invalid wildcard format") | |
} | |
cidr := "" | |
for i, part := range parts { | |
if part == "*" { | |
parts[i] = "0" | |
} | |
cidr += parts[i] | |
if i < 3 { | |
cidr += "." | |
} | |
} | |
wildcardCount := strings.Count(wildcard, "*") | |
if wildcardCount < 1 || wildcardCount > 4 { | |
return nil, fmt.Errorf("invalid wildcard usage") | |
} | |
// Calculate CIDR block size based on wildcard count | |
cidrBlockSize := 32 - (wildcardCount * 8) | |
cidr += fmt.Sprintf("/%d", cidrBlockSize) | |
return []string{cidr}, nil | |
} | |
func generateIPsFromCIDR(ipnet *net.IPNet) []net.IP { | |
var ips []net.IP | |
for ip := ipnet.IP.Mask(ipnet.Mask); ipnet.Contains(ip); incrementIP(ip) { | |
ips = append(ips, net.ParseIP(ip.String())) | |
} | |
return ips | |
} | |
func incrementIP(ip net.IP) { | |
for j := len(ip) - 1; j >= 0; j-- { | |
ip[j]++ | |
if ip[j] > 0 { | |
break | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment