package client import ( "fmt" "net" "net/url" "strings" "time" ) // ConnectivityProbeReport is diagnostic-only reachability (not a C2 channel). type ConnectivityProbeReport struct { C2Host string `json:"c2_host"` C2DNSOK bool `json:"c2_dns_ok"` C2DNSAddrs []string `json:"c2_dns_addrs,omitempty"` C2TCPOK bool `json:"c2_tcp_ok"` C2TCPError string `json:"c2_tcp_error,omitempty"` PoolHost string `json:"pool_host,omitempty"` PoolDNSOK bool `json:"pool_dns_ok,omitempty"` PoolDNSAddrs []string `json:"pool_dns_addrs,omitempty"` PoolTCPOK bool `json:"pool_tcp_ok,omitempty"` PoolTCPError string `json:"pool_tcp_error,omitempty"` } func runConnectivityProbe(serverURL, poolHost string, poolPort int) ConnectivityProbeReport { report := ConnectivityProbeReport{} host, port, err := hostPortFromServerURL(serverURL) if err != nil { report.C2Host = serverURL report.C2TCPError = err.Error() return report } report.C2Host = net.JoinHostPort(host, port) report.C2DNSOK, report.C2DNSAddrs = probeDNSResolve(host) report.C2TCPOK, report.C2TCPError = probeTCPConnect(host, port) if poolHost != "" { pport := poolPort if pport <= 0 { pport = 3333 } pportStr := fmt.Sprintf("%d", pport) report.PoolHost = net.JoinHostPort(poolHost, pportStr) report.PoolDNSOK, report.PoolDNSAddrs = probeDNSResolve(poolHost) report.PoolTCPOK, report.PoolTCPError = probeTCPConnect(poolHost, pportStr) } return report } func hostPortFromServerURL(serverURL string) (host, port string, err error) { raw := strings.TrimSpace(serverURL) if raw == "" { return "", "", fmt.Errorf("empty server URL") } if !strings.Contains(raw, "://") { raw = "http://" + raw } u, err := url.Parse(raw) if err != nil { return "", "", err } host = u.Hostname() port = u.Port() if port == "" { if u.Scheme == "https" { port = "443" } else { port = "80" } } if host == "" { return "", "", fmt.Errorf("no host in server URL") } return host, port, nil } func probeDNSResolve(host string) (bool, []string) { addrs, err := net.LookupHost(host) if err != nil || len(addrs) == 0 { return false, nil } return true, addrs } func probeTCPConnect(host, port string) (bool, string) { addr := net.JoinHostPort(host, port) conn, err := net.DialTimeout("tcp", addr, 5*time.Second) if err != nil { return false, err.Error() } _ = conn.Close() return true, "" }