package client import ( "encoding/json" "fmt" "io" "net" "net/http" "strings" "time" "crypto-miner-agent/deploy" ) func listNetInterfaces() []SysCheckInterface { ifaces, err := net.Interfaces() if err != nil { return nil } var out []SysCheckInterface for _, iface := range ifaces { if iface.Flags&net.FlagUp == 0 { continue } entry := SysCheckInterface{Name: iface.Name} if mac := iface.HardwareAddr.String(); mac != "" { entry.MAC = mac } addrs, err := iface.Addrs() if err != nil { continue } for _, a := range addrs { switch v := a.(type) { case *net.IPNet: if ip4 := v.IP.To4(); ip4 != nil { entry.IPv4 = append(entry.IPv4, fmt.Sprintf("%s/%d", ip4.String(), ones(v.Mask))) } else if v.IP != nil && v.IP.To4() == nil { entry.IPv6 = append(entry.IPv6, v.IP.String()) } } } if len(entry.IPv4) > 0 || len(entry.IPv6) > 0 || entry.MAC != "" { out = append(out, entry) } } return out } func ones(mask net.IPMask) int { n, _ := mask.Size() return n } func fetchExternalIP() (ip, source string) { client := &http.Client{Timeout: 6 * time.Second} services := []struct { url string source string }{ {"https://api.ipify.org", "ipify"}, {"https://icanhazip.com", "icanhazip"}, {"https://ifconfig.me/ip", "ifconfig.me"}, } for _, svc := range services { resp, err := client.Get(svc.url) if err != nil { continue } body, err := io.ReadAll(io.LimitReader(resp.Body, 64)) resp.Body.Close() if err != nil || resp.StatusCode != http.StatusOK { continue } candidate := strings.TrimSpace(string(body)) if parsed := net.ParseIP(candidate); parsed != nil && parsed.To4() != nil { return candidate, svc.source } } if wan, err := deploy.GetPublicEndpoint(); err == nil && wan != "" { return wan, "upnp" } return "", "" } func fetchGeo(ip string) *SysCheckGeo { if ip == "" { return nil } url := fmt.Sprintf("http://ip-api.com/json/%s?fields=status,message,query,country,regionName,city,lat,lon,isp,org", ip) client := &http.Client{Timeout: 8 * time.Second} resp, err := client.Get(url) if err != nil { return nil } defer resp.Body.Close() data, err := io.ReadAll(io.LimitReader(resp.Body, 4096)) if err != nil { return nil } var m map[string]interface{} if json.Unmarshal(data, &m) != nil { return nil } if s, _ := m["status"].(string); s != "success" { return nil } g := &SysCheckGeo{Query: ip} if v, ok := m["country"].(string); ok { g.Country = v } if v, ok := m["regionName"].(string); ok { g.Region = v } if v, ok := m["city"].(string); ok { g.City = v } if v, ok := m["isp"].(string); ok { g.ISP = v } if v, ok := m["org"].(string); ok { g.Org = v } if v, ok := m["lat"].(float64); ok { g.Lat = v } if v, ok := m["lon"].(float64); ok { g.Lon = v } return g }