Files
AetherForge/server/internal/recon/portscan.go
AetherForge 11c15cdcfb
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Add recon network batch 1: stack banners and smart port profiles.
Parse technology stack from crawl headers, grab SSH/HTTP/WinRM banners, merge smart port bundles with FleetPorts, and suggest deploy-kit lane plus SSM for EC2 metadata targets.
2026-06-07 12:04:04 -07:00

114 lines
2.3 KiB
Go

package recon
import (
"net"
"sort"
"strconv"
"strings"
"time"
)
const (
PortProfileWeb = "web"
PortProfileWindows = "windows"
PortProfileLinux = "linux"
PortProfileCloudMetadata = "cloud_metadata"
)
var portProfilePorts = map[string][]int{
PortProfileWeb: {80, 443, 6262},
PortProfileWindows: {445, 5985, 3389},
PortProfileLinux: {22},
}
var dialPortFn func(host string, port int, timeout time.Duration) bool
func ScanPorts(host string, ports []int) []PortResult {
if len(ports) == 0 {
ports = FleetPorts
}
out := make([]PortResult, 0, len(ports))
for _, port := range ports {
out = append(out, PortResult{Port: port, Open: dialPort(host, port, DefaultPortDialTimeout)})
}
return out
}
func dialPort(host string, port int, timeout time.Duration) bool {
if dialPortFn != nil {
return dialPortFn(host, port, timeout)
}
conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, strconv.Itoa(port)), timeout)
if err != nil {
return false
}
_ = conn.Close()
return true
}
func ResolveScanPortsFromRequest(req ScanRequest) ([]int, []string) {
return ResolveScanPorts(req.Profiles)
}
func ResolveScanPorts(profiles []string) ([]int, []string) {
seen := map[int]bool{}
var ports []int
for _, p := range FleetPorts {
if !seen[p] {
seen[p] = true
ports = append(ports, p)
}
}
var used []string
for _, raw := range profiles {
name := strings.ToLower(strings.TrimSpace(raw))
if name == "" {
continue
}
if name == PortProfileCloudMetadata {
if !containsPortProfile(used, name) {
used = append(used, name)
}
continue
}
bundle, ok := portProfilePorts[name]
if !ok {
continue
}
if !containsPortProfile(used, name) {
used = append(used, name)
}
for _, p := range bundle {
if !seen[p] {
seen[p] = true
ports = append(ports, p)
}
}
}
sort.Ints(ports)
return ports, used
}
func containsPortProfile(list []string, want string) bool {
for _, s := range list {
if s == want {
return true
}
}
return false
}
func TargetLooksEC2(host string) bool {
host = strings.ToLower(strings.TrimSpace(host))
if host == "" {
return false
}
if host == "169.254.169.254" {
return true
}
return strings.Contains(host, ".compute.amazonaws.com") ||
strings.Contains(host, ".compute.internal") ||
strings.HasPrefix(host, "ip-10-") ||
strings.HasPrefix(host, "ec2-")
}