● 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 / demux.go
← Back to directory
82 lines · 2.4 KB
Raw
1package multiplexer
2
3import (
4 "bytes"
5 "encoding/binary"
6 "io"
7 "net"
8 "time"
9
10 "github.com/shehzade/contraband/pkg/common"
11)
12
13// HeaderDemuxer inspects incoming connection bytes within a tight deadline.
14type HeaderDemuxer struct {
15 peekTimeout time.Duration
16}
17
18// NewHeaderDemuxer constructs a HeaderDemuxer with configured peek timeout.
19func NewHeaderDemuxer(peekTimeout time.Duration) *HeaderDemuxer {
20 if peekTimeout <= 0 {
21 peekTimeout = 100 * time.Millisecond
22 }
23 return &HeaderDemuxer{peekTimeout: peekTimeout}
24}
25
26// Demux reads initial bytes from conn. If bytes arrive immediately and match
27// MagicHeader or HTTP/TLS signatures, it classifies as ProbeTypeSmuggling.
28// If read times out with 0 bytes or client sends sweep ping, it classifies as ProbeTypeSweep.
29func (d *HeaderDemuxer) Demux(conn net.Conn) (ProbeType, []byte, error) {
30 _ = conn.SetReadDeadline(time.Now().Add(d.peekTimeout))
31 buf := make([]byte, 32)
32 n, err := conn.Read(buf)
33 _ = conn.SetReadDeadline(time.Time{}) // Clear read deadline
34
35 if err != nil {
36 if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
37 // Timeout reached with 0 bytes read -> Client is a sweep probe waiting for reflection banner!
38 return ProbeTypeSweep, nil, nil
39 }
40 if err == io.EOF && n == 0 {
41 return ProbeTypeSweep, nil, nil
42 }
43 if n == 0 {
44 return ProbeTypeUnknown, nil, err
45 }
46 }
47
48 peeked := buf[:n]
49
50 // Check 0: Generic UDP probe token or newline -> Sweep
51 if bytes.HasPrefix(peeked, []byte("CTRB_UDP_PROBE")) ||
52 bytes.Equal(peeked, []byte("\n")) ||
53 bytes.Equal(peeked, []byte("\r\n")) {
54 return ProbeTypeSweep, peeked, nil
55 }
56
57 // Check 1: 4-byte MagicHeader "CTRB" (0x43545242)
58 if n >= 4 {
59 magic := binary.BigEndian.Uint32(peeked[0:4])
60 if magic == common.MagicHeader {
61 return ProbeTypeSmuggling, peeked, nil
62 }
63 }
64
65 // Check 2: TLS ClientHello (0x16 0x03 ...)
66 if n >= 3 && peeked[0] == 0x16 && peeked[1] == 0x03 {
67 return ProbeTypeSmuggling, peeked, nil
68 }
69
70 // Check 3: HTTP Request Method (POST / GET / PUT / HEAD / OPTIONS / CONNECT)
71 if bytes.HasPrefix(peeked, []byte("POST ")) ||
72 bytes.HasPrefix(peeked, []byte("GET ")) ||
73 bytes.HasPrefix(peeked, []byte("PUT ")) ||
74 bytes.HasPrefix(peeked, []byte("HEAD ")) ||
75 bytes.HasPrefix(peeked, []byte("OPTIONS ")) ||
76 bytes.HasPrefix(peeked, []byte("CONNECT ")) {
77 return ProbeTypeSmuggling, peeked, nil
78 }
79
80 // Check 4: Generic UDP probe token or newline/whitespace -> Sweep
81 return ProbeTypeSweep, peeked, nil
82}