Просмотр исходного кода

Add base faketls processing

tags/v2.0.0-rc1
9seconds 5 лет назад
Родитель
Сommit
c3e8e8b1fe

+ 1
- 0
go.mod Просмотреть файл

22
 	github.com/stretchr/testify v1.7.0
22
 	github.com/stretchr/testify v1.7.0
23
 	github.com/tylertreat/BoomFilters v0.0.0-20200520150052-42a7b4300c0c
23
 	github.com/tylertreat/BoomFilters v0.0.0-20200520150052-42a7b4300c0c
24
 	github.com/xeipuuv/gojsonschema v1.2.0
24
 	github.com/xeipuuv/gojsonschema v1.2.0
25
+	golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect
25
 	golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
26
 	golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
26
 	golang.org/x/sys v0.0.0-20210309074719-68d13333faf2 // indirect
27
 	golang.org/x/sys v0.0.0-20210309074719-68d13333faf2 // indirect
27
 )
28
 )

+ 2
- 0
go.sum Просмотреть файл

324
 golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
324
 golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
325
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
325
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
326
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
326
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
327
+golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
328
+golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
327
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
329
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
328
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
330
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
329
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
331
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=

+ 12
- 8
mtglib/internal/faketls/client_hello.go Просмотреть файл

11
 )
11
 )
12
 
12
 
13
 type ClientHello struct {
13
 type ClientHello struct {
14
-	Time      time.Time
15
-	Digest    [RandomLen]byte
16
-	SessionID []byte
14
+	Time        time.Time
15
+	Random      [RandomLen]byte
16
+	SessionID   []byte
17
+	CipherSuite uint16
17
 }
18
 }
18
 
19
 
19
 func ParseClientHello(secret, handshake []byte) (ClientHello, error) {
20
 func ParseClientHello(secret, handshake []byte) (ClientHello, error) {
27
 		return hello, fmt.Errorf("unknown handshake type %#x", handshake[0])
28
 		return hello, fmt.Errorf("unknown handshake type %#x", handshake[0])
28
 	}
29
 	}
29
 
30
 
30
-	copy(hello.Digest[:], handshake[ClientHelloRandomOffset:])
31
+	copy(hello.Random[:], handshake[ClientHelloRandomOffset:])
31
 
32
 
32
 	for i := ClientHelloRandomOffset; i < ClientHelloRandomOffset+RandomLen; i++ {
33
 	for i := ClientHelloRandomOffset; i < ClientHelloRandomOffset+RandomLen; i++ {
33
 		handshake[i] = 0
34
 		handshake[i] = 0
45
 	mac := hmac.New(sha256.New, secret)
46
 	mac := hmac.New(sha256.New, secret)
46
 	rec.Dump(mac)
47
 	rec.Dump(mac)
47
 
48
 
48
-	computedDigest := mac.Sum(nil)
49
+	computedRandom := mac.Sum(nil)
49
 
50
 
50
 	for i := 0; i < RandomLen; i++ {
51
 	for i := 0; i < RandomLen; i++ {
51
-		computedDigest[i] ^= hello.Digest[i]
52
+		computedRandom[i] ^= hello.Random[i]
52
 	}
53
 	}
53
 
54
 
54
 	for i := 0; i < RandomLen-4; i++ {
55
 	for i := 0; i < RandomLen-4; i++ {
55
-		if computedDigest[i] != 0 {
56
+		if computedRandom[i] != 0 {
56
 			return hello, ErrBadDigest
57
 			return hello, ErrBadDigest
57
 		}
58
 		}
58
 	}
59
 	}
59
 
60
 
60
-	timestamp := int64(binary.LittleEndian.Uint32(computedDigest[RandomLen-4:]))
61
+	timestamp := int64(binary.LittleEndian.Uint32(computedRandom[RandomLen-4:]))
61
 	hello.Time = time.Unix(timestamp, 0)
62
 	hello.Time = time.Unix(timestamp, 0)
62
 
63
 
63
 	hello.SessionID = make([]byte, handshake[ClientHelloSessionIDOffset])
64
 	hello.SessionID = make([]byte, handshake[ClientHelloSessionIDOffset])
64
 	copy(hello.SessionID, handshake[ClientHelloSessionIDOffset+1:])
65
 	copy(hello.SessionID, handshake[ClientHelloSessionIDOffset+1:])
65
 
66
 
67
+	cipherSuiteOffset := ClientHelloSessionIDOffset + 1 + len(hello.SessionID) + 2
68
+	hello.CipherSuite = binary.BigEndian.Uint16(handshake[cipherSuiteOffset : cipherSuiteOffset+2])
69
+
66
 	return hello, nil
70
 	return hello, nil
67
 }
71
 }

+ 16
- 1
mtglib/internal/faketls/init.go Просмотреть файл

7
 
7
 
8
 	ClientHelloRandomOffset    = 6
8
 	ClientHelloRandomOffset    = 6
9
 	ClientHelloSessionIDOffset = ClientHelloRandomOffset + RandomLen
9
 	ClientHelloSessionIDOffset = ClientHelloRandomOffset + RandomLen
10
-	ClientHelloMinLen      = ClientHelloSessionIDOffset + 1
10
+	ClientHelloMinLen          = ClientHelloSessionIDOffset + 1
11
+
12
+	WelcomePacketRandomOffset = 11
11
 
13
 
12
 	HandshakeTypeClient = 0x01
14
 	HandshakeTypeClient = 0x01
15
+	HandshakeTypeServer = 0x02
13
 )
16
 )
14
 
17
 
15
 var (
18
 var (
16
 	ErrBadDigest        = errors.New("bad digest")
19
 	ErrBadDigest        = errors.New("bad digest")
17
 	ErrAntiReplayAttack = errors.New("antireplay attack was detected")
20
 	ErrAntiReplayAttack = errors.New("antireplay attack was detected")
21
+
22
+	serverHelloSuffix = []byte{
23
+		0x00,       // no compression
24
+		0x00, 0x2e, // 46 bytes of data
25
+		0x00, 0x2b, // Extension - Supported Versions
26
+		0x00, 0x02, // 2 bytes are following
27
+		0x03, 0x04, // TLS 1.3
28
+		0x00, 0x33, // Extension - Key Share
29
+		0x00, 0x24, // 36 bytes
30
+		0x00, 0x1d, // x25519 curve
31
+		0x00, 0x20, // 32 bytes of key
32
+	}
18
 )
33
 )

+ 21
- 0
mtglib/internal/faketls/pools.go Просмотреть файл

1
+package faketls
2
+
3
+import (
4
+	"bytes"
5
+	"sync"
6
+)
7
+
8
+var bytesBufferPool = sync.Pool{
9
+	New: func() interface{} {
10
+		return &bytes.Buffer{}
11
+	},
12
+}
13
+
14
+func acquireBytesBuffer() *bytes.Buffer {
15
+    return bytesBufferPool.Get().(*bytes.Buffer)
16
+}
17
+
18
+func releaseBytesBuffer(b *bytes.Buffer) {
19
+    b.Reset()
20
+    bytesBufferPool.Put(b)
21
+}

+ 88
- 0
mtglib/internal/faketls/welcome.go Просмотреть файл

1
+package faketls
2
+
3
+import (
4
+	"crypto/hmac"
5
+	"crypto/rand"
6
+	"crypto/sha256"
7
+	"encoding/binary"
8
+	"io"
9
+	mrand "math/rand"
10
+
11
+	"github.com/9seconds/mtg/v2/mtglib/internal/faketls/record"
12
+	"golang.org/x/crypto/curve25519"
13
+)
14
+
15
+func SendWelcomePacket(writer io.Writer, secret []byte, clientHello ClientHello) error {
16
+	buf := acquireBytesBuffer()
17
+	defer releaseBytesBuffer(buf)
18
+
19
+	rec := record.AcquireRecord()
20
+	defer record.ReleaseRecord(rec)
21
+
22
+	rec.Type = record.TypeHandshake
23
+	rec.Version = record.Version12
24
+
25
+	generateServerHello(&rec.Payload, clientHello)
26
+	rec.Dump(buf)
27
+	rec.Reset()
28
+
29
+	rec.Type = record.TypeChangeCipherSpec
30
+	rec.Version = record.Version12
31
+	rec.Payload.WriteByte(0x01)
32
+
33
+	rec.Dump(buf)
34
+	rec.Reset()
35
+
36
+	rec.Type = record.TypeApplicationData
37
+	rec.Version = record.Version12
38
+
39
+	if _, err := io.CopyN(&rec.Payload, rand.Reader, int64(1024+mrand.Intn(3092))); err != nil {
40
+		panic(err)
41
+	}
42
+
43
+	rec.Dump(buf)
44
+
45
+	packet := buf.Bytes()
46
+	mac := hmac.New(sha256.New, secret)
47
+
48
+	mac.Write(clientHello.Random[:])
49
+	mac.Write(packet)
50
+
51
+	copy(packet[WelcomePacketRandomOffset:], mac.Sum(nil))
52
+
53
+	if _, err := writer.Write(packet); err != nil {
54
+		return err // nolint: wrapcheck
55
+	}
56
+
57
+	return nil
58
+}
59
+
60
+func generateServerHello(writer io.Writer, clientHello ClientHello) {
61
+	bodyBuf := acquireBytesBuffer()
62
+	defer releaseBytesBuffer(bodyBuf)
63
+
64
+	sliceBuf := [2]byte{}
65
+	digest := [RandomLen]byte{}
66
+
67
+	binary.BigEndian.PutUint16(sliceBuf[:], uint16(record.Version12))
68
+	bodyBuf.Write(sliceBuf[:])
69
+	bodyBuf.Write(digest[:])
70
+	bodyBuf.WriteByte(byte(len(clientHello.SessionID)))
71
+	bodyBuf.Write(clientHello.SessionID)
72
+
73
+	binary.BigEndian.PutUint16(sliceBuf[:], clientHello.CipherSuite)
74
+	bodyBuf.Write(sliceBuf[:])
75
+	bodyBuf.Write(serverHelloSuffix)
76
+
77
+	scalar := [32]byte{}
78
+	rand.Read(scalar[:])
79
+	curve, _ := curve25519.X25519(scalar[:], curve25519.Basepoint)
80
+	bodyBuf.Write(curve)
81
+
82
+	header := [4]byte{0, 0, 0, 0}
83
+	binary.BigEndian.PutUint32(header[:], uint32(bodyBuf.Len()))
84
+	header[0] = HandshakeTypeServer
85
+
86
+	writer.Write(header[:])
87
+	bodyBuf.WriteTo(writer)
88
+}

+ 10
- 6
mtglib/proxy.go Просмотреть файл

122
 }
122
 }
123
 
123
 
124
 func (p *Proxy) doFakeTLSHandshake(ctx *streamContext, conn net.Conn) error {
124
 func (p *Proxy) doFakeTLSHandshake(ctx *streamContext, conn net.Conn) error {
125
-	clientHelloRecord := record.AcquireRecord()
126
-	defer record.ReleaseRecord(clientHelloRecord)
125
+	rec := record.AcquireRecord()
126
+	defer record.ReleaseRecord(rec)
127
 
127
 
128
-	if err := clientHelloRecord.Read(conn); err != nil {
128
+	if err := rec.Read(conn); err != nil {
129
 		return fmt.Errorf("cannot read client hello: %w", err)
129
 		return fmt.Errorf("cannot read client hello: %w", err)
130
 	}
130
 	}
131
 
131
 
132
-	hello, err := faketls.ParseClientHello(p.secret.Key[:],
133
-		clientHelloRecord.Payload.Bytes())
132
+	hello, err := faketls.ParseClientHello(p.secret.Key[:], rec.Payload.Bytes())
134
 	if err != nil {
133
 	if err != nil {
135
 		return fmt.Errorf("cannot parse client hello: %w", err)
134
 		return fmt.Errorf("cannot parse client hello: %w", err)
136
 	}
135
 	}
138
 	if err := p.timeAttackDetector.Valid(hello.Time); err != nil {
137
 	if err := p.timeAttackDetector.Valid(hello.Time); err != nil {
139
 		return fmt.Errorf("invalid time: %w", err)
138
 		return fmt.Errorf("invalid time: %w", err)
140
 	}
139
 	}
140
+
141
 	if p.antiReplayCache.SeenBefore(hello.SessionID) {
141
 	if p.antiReplayCache.SeenBefore(hello.SessionID) {
142
 		p.logger.Warning("anti replay attack was detected")
142
 		p.logger.Warning("anti replay attack was detected")
143
 
143
 
144
 		return fmt.Errorf("anti replay attack from %s", ctx.ClientIP().String())
144
 		return fmt.Errorf("anti replay attack from %s", ctx.ClientIP().String())
145
 	}
145
 	}
146
 
146
 
147
-	return fmt.Errorf("SUCCESS")
147
+	if err := faketls.SendWelcomePacket(conn, p.secret.Key[:], hello); err != nil {
148
+		return fmt.Errorf("cannot send a welcome packet: %w", err)
149
+	}
150
+
151
+	return nil
148
 }
152
 }
149
 
153
 
150
 func (p *Proxy) doObfuscated2Handshake(ctx *streamContext) error {
154
 func (p *Proxy) doObfuscated2Handshake(ctx *streamContext) error {

Загрузка…
Отмена
Сохранить