● Notice //GitHub (@shehzade) is temporarily suspended pending an automated false-positive review. All tools are hosted on this Code Mirror and available on request (contact); GitHub links will return once reinstated.
PUBLIC MIRRORGo v1.0

Multi-protocol network egress assessment and DLP verification framework featuring automated L4 sweeps, corporate proxy traversal, and covert protocol smuggling across 20+ channels.

$ git clone https://shehzade.io/repos/contraband.git Copy
Source ZIP (1.93 MB)
Code 174 Commits 1
contraband / pkg / soak / runner.go
← Back to directory
194 lines · 6.0 KB
Raw
1package soak
2
3import (
4 "context"
5 "fmt"
6 "runtime"
7 "sync"
8 "time"
9
10 "github.com/shehzade/contraband/pkg/common"
11)
12
13// SoakRunner coordinates persistent continuous multi-zone execution across the 8-10 hour window.
14type SoakRunner struct {
15 engine *SoakEngine
16 logger common.Logger
17}
18
19// NewSoakRunner wraps a SoakEngine for daemonized or bounded execution.
20func NewSoakRunner(engine *SoakEngine) *SoakRunner {
21 return &SoakRunner{
22 engine: engine,
23 logger: common.GetLogger(),
24 }
25}
26
27// Engine returns the underlying SoakEngine.
28func (r *SoakRunner) Engine() *SoakEngine {
29 return r.engine
30}
31
32// RunValidationRound executes a rapid verification round across micro, medium, and bulk tiers
33// to validate all pathways, memory ceiling invariants, and dashboard report sync.
34func (r *SoakRunner) RunValidationRound(ctx context.Context) error {
35 r.logger.Info("Starting Pre-Soak Validation Pass (Micro, Medium, Bulk tiers)...")
36 r.engine.startTime = time.Now().UTC()
37 r.engine.memMonitor.Start(ctx)
38
39 valMatrix := GenerateScenarioMatrix(r.engine.config.ValidationVolumes)
40 r.logger.Info(fmt.Sprintf("Validation matrix generated: %d scenarios across %d zones and %d protocols",
41 len(valMatrix), len(AllZones()), len(AllSoakProtocols())))
42
43 // Distribute scenarios into zone queues
44 zoneQueues := make(map[string][]Scenario)
45 for _, sc := range valMatrix {
46 zoneQueues[sc.Zone] = append(zoneQueues[sc.Zone], sc)
47 }
48
49 var wg sync.WaitGroup
50 for zone, queue := range zoneQueues {
51 wg.Add(1)
52 go func(z string, q []Scenario) {
53 defer wg.Done()
54 for _, sc := range q {
55 select {
56 case <-ctx.Done():
57 return
58 default:
59 _ = r.engine.ExecuteScenario(ctx, sc)
60 runtime.GC()
61 time.Sleep(10 * time.Millisecond)
62 }
63 }
64 // Sync zone report to live dashboard
65 _ = r.engine.GenerateAndSyncReport(ctx, z)
66 }(zone, queue)
67 }
68
69 wg.Wait()
70
71 summary := r.engine.Summary()
72 r.logger.Success(fmt.Sprintf("Validation Round Complete: %d/%d scenarios verified, %s transferred, Peak Heap: %.2fMB (Invariant Healthy: %t)",
73 summary.SuccessScenarios, summary.TotalScenarios, summary.FormattedBytes, summary.PeakHeapMB, summary.MemoryHealthy))
74
75 if !summary.MemoryHealthy {
76 return fmt.Errorf("memory invariant breached during validation round: peak=%.2fMB, violations=%d",
77 summary.PeakHeapMB, summary.MemoryViolations)
78 }
79
80 return nil
81}
82
83// RunContinuous launches the overnight 8-10 hour continuous multi-scenario soak engine.
84// Executes uninterrupted across all 20 L7 protocols and large transfers until context cancel or duration expiration.
85func (r *SoakRunner) RunContinuous(ctx context.Context) error {
86 r.engine.startTime = time.Now().UTC()
87 r.engine.memMonitor.Start(ctx)
88
89 r.logger.Info(fmt.Sprintf("================================================================================"))
90 r.logger.Info(fmt.Sprintf("OVERNIGHT 8-10 HOUR CONTINUOUS SOAK & LIVE STRESS ENGINE LAUNCHED"))
91 r.logger.Info(fmt.Sprintf("Target: %s | Live Dashboard: %s | Duration: %s",
92 r.engine.config.TargetServer, r.engine.config.DashboardURL, r.engine.config.Duration))
93 r.logger.Info(fmt.Sprintf("Zones: 5 Concurrent | Protocols: 20 L7 Channels | Volumes: 50MB-5GB+ | Memory Ceiling: <32MB"))
94 r.logger.Info(fmt.Sprintf("Continuous Logging: %s", r.engine.config.LogPath))
95 r.logger.Info(fmt.Sprintf("================================================================================"))
96
97 r.engine.logger.LogInfo(fmt.Sprintf("Soak engine started with %d scenarios in primary matrix. Duration: %s",
98 len(r.engine.matrix), r.engine.config.Duration))
99
100 zones := AllZones()
101 scenariosByZone := make(map[string][]Scenario)
102 for _, sc := range r.engine.matrix {
103 scenariosByZone[sc.Zone] = append(scenariosByZone[sc.Zone], sc)
104 }
105
106 // Periodic report sync & memory status logger
107 reportTicker := time.NewTicker(r.engine.config.ReportInterval)
108 defer reportTicker.Stop()
109
110 go func() {
111 for {
112 select {
113 case <-ctx.Done():
114 return
115 case <-reportTicker.C:
116 memStats := r.engine.memMonitor.Sample()
117 r.engine.logger.LogMemory(memStats)
118 r.logger.Info(fmt.Sprintf("[SOAK MONITOR] %s | Smuggled: %s | Scenarios: %d | Reports: %d",
119 r.engine.memMonitor.FormatStatus(),
120 common.FormatBytes(r.engine.Summary().TotalBytesSmuggled),
121 r.engine.Summary().TotalScenarios,
122 r.engine.Summary().ReportsUploaded))
123
124 // Sync periodic report for each zone to keep HUD spinning
125 for _, z := range zones {
126 _ = r.engine.GenerateAndSyncReport(ctx, z)
127 }
128 }
129 }
130 }()
131
132 // Spawn concurrent worker goroutines for each network zone
133 var wg sync.WaitGroup
134 var errOnce sync.Once
135 var firstErr error
136
137 for _, zone := range zones {
138 wg.Add(1)
139 go func(z string) {
140 defer wg.Done()
141 q := scenariosByZone[z]
142 if len(q) == 0 {
143 q = r.engine.matrix
144 }
145
146 idx := 0
147 round := 1
148
149 for {
150 select {
151 case <-ctx.Done():
152 return
153 default:
154 }
155
156 sc := q[idx]
157 if err := r.engine.ExecuteScenario(ctx, sc); err != nil {
158 // Scenarios classify errors into verdicts without aborting soak
159 }
160
161 idx++
162 if idx >= len(q) {
163 idx = 0
164 round++
165 r.logger.Info(fmt.Sprintf("[ZONE %s] Completed round %d across all scenario matrix permutations", z, round-1))
166 _ = r.engine.GenerateAndSyncReport(ctx, z)
167 }
168
169 // Brief yield to avoid CPU spinning when transfers complete
170 time.Sleep(50 * time.Millisecond)
171 }
172 }(zone)
173 }
174
175 // Wait for context cancellation or timeout
176 select {
177 case <-ctx.Done():
178 r.logger.Info("Soak engine received termination signal or duration elapsed. Initiating graceful shutdown...")
179 }
180
181 wg.Wait()
182
183 finalSummary := r.engine.Summary()
184 r.logger.Success(fmt.Sprintf("Soak engine shutdown complete. Elapsed: %.2fms | Total Scenarios: %d | Success: %d | Peak Heap: %.2fMB | Invariant Healthy: %t",
185 finalSummary.ElapsedMS, finalSummary.TotalScenarios, finalSummary.SuccessScenarios, finalSummary.PeakHeapMB, finalSummary.MemoryHealthy))
186
187 errOnce.Do(func() {
188 if !finalSummary.MemoryHealthy {
189 firstErr = fmt.Errorf("memory ceiling <32MB invariant breached during soak run")
190 }
191 })
192
193 return firstErr
194}