● 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 / server / multiplexer / reflector.go
← Back to directory
153 lines · 3.7 KB
Raw
1package multiplexer
2
3import (
4 "encoding/json"
5 "fmt"
6 "net"
7 "time"
8
9 "github.com/shehzade/contraband/pkg/common"
10 "github.com/shehzade/contraband/pkg/server"
11)
12
13// ReflectionEngine emits authenticated JSON reflection banners and records ledger probes.
14type ReflectionEngine struct {
15 ledger server.Ledger
16 logger common.Logger
17}
18
19// NewReflectionEngine constructs a ReflectionEngine.
20func NewReflectionEngine(ledger server.Ledger, logger common.Logger) *ReflectionEngine {
21 if logger == nil {
22 logger = common.GetLogger()
23 }
24 return &ReflectionEngine{
25 ledger: ledger,
26 logger: logger,
27 }
28}
29
30// ReflectTCP emits common.BannerReflection JSON to a connected TCP client.
31func (r *ReflectionEngine) ReflectTCP(conn net.Conn, port int) error {
32 remoteAddr := conn.RemoteAddr().String()
33 clientIP, _, err := net.SplitHostPort(remoteAddr)
34 if err != nil {
35 clientIP = remoteAddr
36 }
37
38 sessionToken, err := common.NewSessionToken()
39 if err != nil {
40 sessionToken = common.SessionToken{0x01, 0x02, 0x03, 0x04}
41 }
42 sessionID := sessionToken.String()
43 if len(sessionID) > 16 {
44 sessionID = sessionID[:16]
45 }
46
47 bannerObj := common.BannerReflection{
48 Status: "OK",
49 RemoteIP: clientIP,
50 Port: port,
51 Proto: "TCP",
52 Session: sessionID,
53 }
54
55 bannerBytes, err := json.Marshal(bannerObj)
56 if err != nil {
57 return fmt.Errorf("failed to marshal banner JSON: %w", err)
58 }
59 bannerBytes = append(bannerBytes, '\n')
60
61 _ = conn.SetWriteDeadline(time.Now().Add(1500 * time.Millisecond))
62 n, writeErr := conn.Write(bannerBytes)
63
64 // Record probe in Ledger if available
65 if r.ledger != nil {
66 now := time.Now().UTC()
67 probeID, _ := common.GenerateUUIDv4()
68 probe := common.ProbeResult{
69 ID: probeID,
70 Timestamp: now,
71 Timestamps: common.ForensicTimestamps{
72 StartTCP: now,
73 ConnectedTCP: now,
74 AckReceived: now,
75 TeardownDone: now,
76 },
77 Stage: "sweep",
78 Protocol: "tcp_sweep",
79 TargetPort: port,
80 TargetHost: conn.LocalAddr().String(),
81 LocalAddr: remoteAddr,
82 BytesSent: int64(n),
83 BytesRecv: 0,
84 Verdict: common.VerdictSuccess,
85 RawEvidence: string(bannerBytes),
86 }
87 _ = r.ledger.RecordProbe(probe)
88 }
89
90 return writeErr
91}
92
93// ReflectUDP emits common.BannerReflection JSON to a UDP probe client.
94func (r *ReflectionEngine) ReflectUDP(pc net.PacketConn, rAddr net.Addr, port int, data []byte) error {
95 remoteAddr := rAddr.String()
96 clientIP, _, err := net.SplitHostPort(remoteAddr)
97 if err != nil {
98 clientIP = remoteAddr
99 }
100
101 sessionToken, err := common.NewSessionToken()
102 if err != nil {
103 sessionToken = common.SessionToken{0x01, 0x02, 0x03, 0x04}
104 }
105 sessionID := sessionToken.String()
106 if len(sessionID) > 16 {
107 sessionID = sessionID[:16]
108 }
109
110 bannerObj := common.BannerReflection{
111 Status: "OK",
112 RemoteIP: clientIP,
113 Port: port,
114 Proto: "UDP",
115 Session: sessionID,
116 }
117
118 bannerBytes, err := json.Marshal(bannerObj)
119 if err != nil {
120 return fmt.Errorf("failed to marshal banner JSON: %w", err)
121 }
122 bannerBytes = append(bannerBytes, '\n')
123
124 n, writeErr := pc.WriteTo(bannerBytes, rAddr)
125
126 // Record probe in Ledger if available
127 if r.ledger != nil {
128 now := time.Now().UTC()
129 probeID, _ := common.GenerateUUIDv4()
130 probe := common.ProbeResult{
131 ID: probeID,
132 Timestamp: now,
133 Timestamps: common.ForensicTimestamps{
134 StartTCP: now,
135 ConnectedTCP: now,
136 AckReceived: now,
137 TeardownDone: now,
138 },
139 Stage: "sweep",
140 Protocol: "udp_sweep",
141 TargetPort: port,
142 TargetHost: pc.LocalAddr().String(),
143 LocalAddr: remoteAddr,
144 BytesSent: int64(n),
145 BytesRecv: int64(len(data)),
146 Verdict: common.VerdictSuccess,
147 RawEvidence: string(bannerBytes),
148 }
149 _ = r.ledger.RecordProbe(probe)
150 }
151
152 return writeErr
153}