● 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 / client / traffic / profiles.go
← Back to directory
275 lines · 7.3 KB
Raw
1package traffic
2
3import (
4 "fmt"
5 "strings"
6 "sync"
7 "sync/atomic"
8 "time"
9
10 "github.com/shehzade/contraband/pkg/common"
11)
12
13// ProfilePreset names
14const (
15 PresetStealth = "stealth"
16 PresetFast = "fast"
17 PresetCovert = "covert"
18 PresetBulk = "bulk"
19)
20
21// TrafficProfile encapsulates complete operational parameters for client egress traffic.
22type TrafficProfile struct {
23 Name string
24 Throughput float64 // Bytes/sec (0.0 = unlimited)
25 Cadence string // burst, steady, jittered, office-hours, low-and-slow
26 IntervalMin time.Duration // Minimum delay
27 IntervalMax time.Duration // Maximum delay
28 Jitter float64 // 0.0 to 1.0
29 Distribution DistributionType // uniform or gaussian
30 Threads int // Worker concurrency (1–64)
31 PacketGap time.Duration // Microsecond gap between packets
32 BurstBytes int64 // Maximum token burst capacity
33}
34
35// PresetStealthProfile returns the stealth egress preset.
36// Rate: 50 KB/s, Interval: 5s–15s, Jitter: 30%, Gaussian distribution, 1 thread.
37func PresetStealthProfile() *TrafficProfile {
38 return &TrafficProfile{
39 Name: PresetStealth,
40 Throughput: 50 * 1024,
41 Cadence: common.CadenceLowAndSlow,
42 IntervalMin: 5 * time.Second,
43 IntervalMax: 15 * time.Second,
44 Jitter: 0.30,
45 Distribution: DistributionGaussian,
46 Threads: 1,
47 PacketGap: 1000 * time.Microsecond,
48 BurstBytes: 64 * 1024,
49 }
50}
51
52// PresetFastProfile returns maximum throughput line rate preset.
53// Rate: unlimited, 0 delay, 0 jitter, 16 threads.
54func PresetFastProfile() *TrafficProfile {
55 return &TrafficProfile{
56 Name: PresetFast,
57 Throughput: 0.0, // unlimited
58 Cadence: common.CadenceBurst,
59 IntervalMin: 0,
60 IntervalMax: 0,
61 Jitter: 0.0,
62 Distribution: DistributionUniform,
63 Threads: 16,
64 PacketGap: 0,
65 BurstBytes: 4 * 1024 * 1024,
66 }
67}
68
69// PresetCovertProfile returns the covert beaconing preset.
70// Rate: 200 KB/s, Interval: 1s–3s, Jitter: 25%, Gaussian distribution, 2 threads.
71func PresetCovertProfile() *TrafficProfile {
72 return &TrafficProfile{
73 Name: PresetCovert,
74 Throughput: 200 * 1024,
75 Cadence: common.CadenceJittered,
76 IntervalMin: 1 * time.Second,
77 IntervalMax: 3 * time.Second,
78 Jitter: 0.25,
79 Distribution: DistributionGaussian,
80 Threads: 2,
81 PacketGap: 500 * time.Microsecond,
82 BurstBytes: 128 * 1024,
83 }
84}
85
86// PresetBulkProfile returns the bulk transfer preset.
87// Rate: 10 MB/s, Interval: 10ms–50ms, Jitter: 5%, Uniform distribution, 8 threads.
88func PresetBulkProfile() *TrafficProfile {
89 return &TrafficProfile{
90 Name: PresetBulk,
91 Throughput: 10 * 1024 * 1024,
92 Cadence: common.CadenceSteady,
93 IntervalMin: 10 * time.Millisecond,
94 IntervalMax: 50 * time.Millisecond,
95 Jitter: 0.05,
96 Distribution: DistributionUniform,
97 Threads: 8,
98 PacketGap: 50 * time.Microsecond,
99 BurstBytes: 2 * 1024 * 1024,
100 }
101}
102
103// FromConfig constructs a TrafficProfile from common.TrafficConfig.
104func FromConfig(cfg common.TrafficConfig) (*TrafficProfile, error) {
105 rate, err := common.ParseBandwidthRate(cfg.Throughput)
106 if err != nil {
107 return nil, fmt.Errorf("invalid profile throughput %q: %w", cfg.Throughput, err)
108 }
109
110 var minD, maxD time.Duration
111 if cfg.IntervalMin != "" {
112 minD, err = common.ParseDuration(cfg.IntervalMin)
113 if err != nil {
114 return nil, fmt.Errorf("invalid interval_min %q: %w", cfg.IntervalMin, err)
115 }
116 }
117 if cfg.IntervalMax != "" {
118 maxD, err = common.ParseDuration(cfg.IntervalMax)
119 if err != nil {
120 return nil, fmt.Errorf("invalid interval_max %q: %w", cfg.IntervalMax, err)
121 }
122 }
123
124 jitter := cfg.Jitter
125 if jitter > 1.0 {
126 jitter = jitter / 100.0
127 }
128
129 threads := cfg.Threads
130 if threads <= 0 {
131 threads = common.DefaultThreads
132 }
133
134 cadence := strings.ToLower(cfg.Cadence)
135 if cadence == "" {
136 cadence = common.CadenceSteady
137 }
138
139 return &TrafficProfile{
140 Name: cadence,
141 Throughput: rate,
142 Cadence: cadence,
143 IntervalMin: minD,
144 IntervalMax: maxD,
145 Jitter: jitter,
146 Distribution: DistributionGaussian,
147 Threads: threads,
148 PacketGap: 100 * time.Microsecond,
149 }, nil
150}
151
152// TrafficMetrics tracks lock-free cumulative and instantaneous traffic stats.
153type TrafficMetrics struct {
154 bytesSent atomic.Int64
155 bytesRecv atomic.Int64
156 packetsSent atomic.Int64
157 sleepDurationNs atomic.Int64
158 startTime time.Time
159
160 mu sync.RWMutex
161 samples []rateSample
162}
163
164type rateSample struct {
165 t time.Time
166 bytes int64
167}
168
169// NewTrafficMetrics initializes a new metrics tracker.
170func NewTrafficMetrics() *TrafficMetrics {
171 return &TrafficMetrics{
172 startTime: time.Now(),
173 samples: make([]rateSample, 0, 128),
174 }
175}
176
177func (m *TrafficMetrics) RecordBytesSent(n int64) {
178 if n <= 0 {
179 return
180 }
181 m.bytesSent.Add(n)
182
183 m.mu.Lock()
184 now := time.Now()
185 m.samples = append(m.samples, rateSample{t: now, bytes: n})
186 // Prune samples older than 5 seconds
187 cutoff := now.Add(-5 * time.Second)
188 idx := 0
189 for idx < len(m.samples) && m.samples[idx].t.Before(cutoff) {
190 idx++
191 }
192 if idx > 0 {
193 m.samples = m.samples[idx:]
194 }
195 m.mu.Unlock()
196}
197
198func (m *TrafficMetrics) RecordBytesRecv(n int64) {
199 if n > 0 {
200 m.bytesRecv.Add(n)
201 }
202}
203
204func (m *TrafficMetrics) RecordPacket() {
205 m.packetsSent.Add(1)
206}
207
208func (m *TrafficMetrics) RecordSleep(d time.Duration) {
209 if d > 0 {
210 m.sleepDurationNs.Add(d.Nanoseconds())
211 }
212}
213
214// CurrentThroughputBps returns instant throughput in bytes/sec over the last 1 second window.
215func (m *TrafficMetrics) CurrentThroughputBps() float64 {
216 m.mu.RLock()
217 defer m.mu.RUnlock()
218
219 now := time.Now()
220 windowStart := now.Add(-1 * time.Second)
221 var windowBytes int64
222 for i := len(m.samples) - 1; i >= 0; i-- {
223 if m.samples[i].t.Before(windowStart) {
224 break
225 }
226 windowBytes += m.samples[i].bytes
227 }
228 return float64(windowBytes)
229}
230
231// AverageThroughputBps returns overall average throughput since start.
232func (m *TrafficMetrics) AverageThroughputBps() float64 {
233 elapsed := time.Since(m.startTime).Seconds()
234 if elapsed <= 0 {
235 return 0.0
236 }
237 return float64(m.bytesSent.Load()) / elapsed
238}
239
240// TrafficStats represents an exported thread-safe snapshot.
241type TrafficStats struct {
242 BytesSent int64 `json:"bytes_sent"`
243 BytesRecv int64 `json:"bytes_recv"`
244 PacketsSent int64 `json:"packets_sent"`
245 TotalSleepMS float64 `json:"total_sleep_ms"`
246 CurrentRateString string `json:"current_rate"`
247 AverageRateString string `json:"average_rate"`
248 AverageRateBps float64 `json:"average_rate_bps"`
249 CurrentRateBps float64 `json:"current_rate_bps"`
250 ElapsedTimeSeconds float64 `json:"elapsed_seconds"`
251}
252
253// Snapshot returns an immutable point-in-time snapshot.
254func (m *TrafficMetrics) Snapshot() TrafficStats {
255 sent := m.bytesSent.Load()
256 recv := m.bytesRecv.Load()
257 pkts := m.packetsSent.Load()
258 sleepNs := m.sleepDurationNs.Load()
259 elapsed := time.Since(m.startTime).Seconds()
260
261 currRate := m.CurrentThroughputBps()
262 avgRate := m.AverageThroughputBps()
263
264 return TrafficStats{
265 BytesSent: sent,
266 BytesRecv: recv,
267 PacketsSent: pkts,
268 TotalSleepMS: float64(sleepNs) / 1e6,
269 CurrentRateString: common.FormatBandwidthRate(currRate),
270 AverageRateString: common.FormatBandwidthRate(avgRate),
271 AverageRateBps: avgRate,
272 CurrentRateBps: currRate,
273 ElapsedTimeSeconds: elapsed,
274 }
275}