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

Add base for faketls

tags/1.0^2
9seconds 6 лет назад
Родитель
Сommit
1e428e13fc

+ 35
- 0
faketls/client_protocol.go Просмотреть файл

@@ -0,0 +1,35 @@
1
+package faketls
2
+
3
+import (
4
+	"bufio"
5
+
6
+	"github.com/9seconds/mtg/conntypes"
7
+	"github.com/9seconds/mtg/obfuscated2"
8
+	"github.com/9seconds/mtg/wrappers/stream"
9
+)
10
+
11
+type ClientProtocol struct {
12
+	obfuscated2.ClientProtocol
13
+}
14
+
15
+func (c *ClientProtocol) Handshake(socket conntypes.StreamReadWriteCloser) (conntypes.StreamReadWriteCloser, error) {
16
+	rewinded := stream.NewRewind(socket)
17
+	bufferedReader := bufio.NewReader(rewinded)
18
+
19
+	for _, expected := range faketlsStartBytes {
20
+		if actual, err := bufferedReader.ReadByte(); err != nil || actual != expected {
21
+			return nil, c.simulateWebsite(rewinded)
22
+		}
23
+	}
24
+
25
+	if err := c.tlsHandshake(rewinded); err != nil {
26
+		return nil, c.simulateWebsite(rewinded)
27
+	}
28
+
29
+	conn, err := c.ClientProtocol.Handshake(socket)
30
+	if err != nil {
31
+		return nil, err
32
+	}
33
+
34
+	return conn, err
35
+}

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

@@ -0,0 +1,21 @@
1
+package faketls
2
+
3
+const (
4
+	TLSHandshakeLength = 1 + 2 + 2 + 512
5
+)
6
+
7
+var (
8
+faketlsStartBytes = [...]byte{
9
+	0x16,
10
+	0x03,
11
+	0x01,
12
+	0x02,
13
+	0x00,
14
+	0x01,
15
+	0x00,
16
+	0x01,
17
+	0xfc,
18
+	0x03,
19
+	0x03,
20
+}
21
+)

+ 10
- 0
faketls/telegram_protocol.go Просмотреть файл

@@ -0,0 +1,10 @@
1
+package faketls
2
+
3
+import (
4
+	"github.com/9seconds/mtg/conntypes"
5
+	"github.com/9seconds/mtg/protocol"
6
+)
7
+
8
+func TelegramProtocol(req *protocol.TelegramRequest) (conntypes.StreamReadWriteCloser, error) {
9
+	return nil, nil
10
+}

+ 18
- 40
wrappers/stream/blockcipher.go Просмотреть файл

@@ -1,7 +1,6 @@
1 1
 package stream
2 2
 
3 3
 import (
4
-	"bytes"
5 4
 	"crypto/aes"
6 5
 	"crypto/cipher"
7 6
 	"fmt"
@@ -15,7 +14,7 @@ import (
15 14
 )
16 15
 
17 16
 type wrapperBlockCipher struct {
18
-	buf bytes.Buffer
17
+	bufferedReader
19 18
 
20 19
 	parent    conntypes.StreamReadWriteCloser
21 20
 	encryptor cipher.BlockMode
@@ -40,43 +39,6 @@ func (w *wrapperBlockCipher) WriteTimeout(p []byte, timeout time.Duration) (int,
40 39
 	return w.parent.WriteTimeout(encrypted, timeout)
41 40
 }
42 41
 
43
-func (w *wrapperBlockCipher) Read(p []byte) (int, error) {
44
-	if w.buf.Len() > 0 {
45
-		return w.flush(p)
46
-	}
47
-
48
-	var currentBuffer []byte
49
-	for len(currentBuffer) == 0 || len(currentBuffer)%aes.BlockSize != 0 {
50
-		rv, err := utils.ReadFull(w.parent)
51
-		if err != nil {
52
-			return 0, fmt.Errorf("cannot read data: %w", err)
53
-		}
54
-
55
-		currentBuffer = append(currentBuffer, rv...)
56
-	}
57
-
58
-	w.decryptor.CryptBlocks(currentBuffer, currentBuffer)
59
-	w.buf.Write(currentBuffer)
60
-
61
-	return w.flush(p)
62
-}
63
-
64
-func (w *wrapperBlockCipher) ReadTimeout(p []byte, timeout time.Duration) (int, error) {
65
-	return w.Read(p)
66
-}
67
-
68
-func (w *wrapperBlockCipher) flush(p []byte) (int, error) {
69
-	if w.buf.Len() > len(p) {
70
-		return w.buf.Read(p)
71
-	}
72
-
73
-	sizeToReturn := w.buf.Len()
74
-	copy(p, w.buf.Bytes())
75
-	w.buf.Reset()
76
-
77
-	return sizeToReturn, nil
78
-}
79
-
80 42
 func (w *wrapperBlockCipher) encrypt(p []byte) ([]byte, error) {
81 43
 	if len(p)%aes.BlockSize > 0 {
82 44
 		return nil, fmt.Errorf("incorrect block size %d", len(p))
@@ -110,9 +72,25 @@ func (w *wrapperBlockCipher) RemoteAddr() *net.TCPAddr {
110 72
 
111 73
 func newBlockCipher(parent conntypes.StreamReadWriteCloser,
112 74
 	encryptor, decryptor cipher.BlockMode) conntypes.StreamReadWriteCloser {
113
-	return &wrapperBlockCipher{
75
+	cipher := &wrapperBlockCipher{
114 76
 		parent:    parent,
115 77
 		encryptor: encryptor,
116 78
 		decryptor: decryptor,
117 79
 	}
80
+
81
+	cipher.readFunc = func() ([]byte, error) {
82
+		var currentBuffer []byte
83
+		for len(currentBuffer) == 0 || len(currentBuffer)%aes.BlockSize != 0 {
84
+			rv, err := utils.ReadFull(cipher.parent)
85
+			if err != nil {
86
+				return nil, fmt.Errorf("cannot read data: %w", err)
87
+			}
88
+			currentBuffer = append(currentBuffer, rv...)
89
+		}
90
+		cipher.decryptor.CryptBlocks(currentBuffer, currentBuffer)
91
+
92
+		return currentBuffer, nil
93
+	}
94
+
95
+	return cipher
118 96
 }

+ 43
- 0
wrappers/stream/buffered_reader.go Просмотреть файл

@@ -0,0 +1,43 @@
1
+package stream
2
+
3
+import (
4
+	"bytes"
5
+	"time"
6
+)
7
+
8
+type bufferedReaderReadFunc func() ([]byte, error)
9
+
10
+type bufferedReader struct {
11
+	buf      bytes.Buffer
12
+	readFunc bufferedReaderReadFunc
13
+}
14
+
15
+func (b *bufferedReader) Read(p []byte) (int, error) {
16
+	if b.buf.Len() > 0 {
17
+		return b.flush(p)
18
+	}
19
+
20
+	res, err := b.readFunc()
21
+	if err != nil {
22
+		return 0, err
23
+	}
24
+	b.buf.Write(res)
25
+
26
+	return b.flush(p)
27
+}
28
+
29
+func (b *bufferedReader) ReadTimeout(p []byte, _ time.Duration) (int, error) {
30
+	return b.Read(p)
31
+}
32
+
33
+func (b *bufferedReader) flush(p []byte) (int, error) {
34
+	if b.buf.Len() > len(p) {
35
+		return b.buf.Read(p)
36
+	}
37
+
38
+	sizeToReturn := b.buf.Len()
39
+	copy(p, b.buf.Bytes())
40
+	b.buf.Reset()
41
+
42
+	return sizeToReturn, nil
43
+}

+ 145
- 0
wrappers/stream/faketls.go Просмотреть файл

@@ -0,0 +1,145 @@
1
+package stream
2
+
3
+import (
4
+	"bytes"
5
+	"encoding/binary"
6
+	"errors"
7
+	"fmt"
8
+	"io"
9
+	"net"
10
+	"time"
11
+
12
+	"go.uber.org/zap"
13
+
14
+	"github.com/9seconds/mtg/conntypes"
15
+)
16
+
17
+var (
18
+	errFakeTLSTimeout  = errors.New("timeout")
19
+	fakeTLSWritePrefix = []byte{0x17, 0x03, 0x03}
20
+)
21
+
22
+const faketlsMaxChunkSize = 16384 + 24
23
+
24
+type wrapperFakeTLS struct {
25
+	bufferedReader
26
+
27
+	parent conntypes.StreamReadWriteCloser
28
+}
29
+
30
+func (w *wrapperFakeTLS) Write(p []byte) (int, error) {
31
+	return w.write(p, func(b []byte) (int, error) {
32
+		return w.parent.Write(b)
33
+	})
34
+}
35
+
36
+func (w *wrapperFakeTLS) WriteTimeout(p []byte, timeout time.Duration) (int, error) {
37
+	startTime := time.Now()
38
+
39
+	return w.write(p, func(b []byte) (int, error) {
40
+		elapsed := time.Since(startTime)
41
+		if elapsed > timeout {
42
+			return w.parent.WriteTimeout(b, timeout-elapsed)
43
+		}
44
+		return 0, errFakeTLSTimeout
45
+	})
46
+}
47
+
48
+func (w *wrapperFakeTLS) write(p []byte, writeFunc func([]byte) (int, error)) (int, error) {
49
+	sum := 0
50
+	size := [2]byte{}
51
+
52
+	for len(p) > 0 {
53
+		chunkSize := faketlsMaxChunkSize
54
+		if chunkSize > len(p) {
55
+			chunkSize = len(p)
56
+		}
57
+
58
+		if _, err := writeFunc(fakeTLSWritePrefix); err != nil {
59
+			return sum, err
60
+		}
61
+
62
+		binary.BigEndian.PutUint16(size[:], uint16(chunkSize))
63
+
64
+		if _, err := writeFunc(size[:]); err != nil {
65
+			return sum, err
66
+		}
67
+
68
+		n, err := writeFunc(p[:chunkSize])
69
+		sum += n
70
+
71
+		if err != nil {
72
+			return sum, err
73
+		}
74
+
75
+		p = p[chunkSize:]
76
+	}
77
+
78
+	return sum, nil
79
+}
80
+
81
+func (w *wrapperFakeTLS) Conn() net.Conn {
82
+	return w.parent.Conn()
83
+}
84
+
85
+func (w *wrapperFakeTLS) Logger() *zap.SugaredLogger {
86
+	return w.parent.Logger().Named("faketls")
87
+}
88
+
89
+func (w *wrapperFakeTLS) LocalAddr() *net.TCPAddr {
90
+	return w.parent.LocalAddr()
91
+}
92
+
93
+func (w *wrapperFakeTLS) RemoteAddr() *net.TCPAddr {
94
+	return w.parent.RemoteAddr()
95
+}
96
+
97
+func (w *wrapperFakeTLS) Close() error {
98
+	return w.parent.Close()
99
+}
100
+
101
+func NewFakeTLS(socket conntypes.StreamReadWriteCloser) conntypes.StreamReadWriteCloser {
102
+	faketls := &wrapperFakeTLS{
103
+		parent: socket,
104
+	}
105
+
106
+	faketls.readFunc = func() ([]byte, error) {
107
+		data := &bytes.Buffer{}
108
+		buf := [2]byte{}
109
+		recordType := byte(0x14)
110
+
111
+		for recordType == 0x14 {
112
+			if _, err := io.ReadFull(faketls.parent, buf[:1]); err != nil {
113
+				return nil, fmt.Errorf("cannot read record type: %w", err)
114
+			}
115
+
116
+			switch buf[0] {
117
+			case 0x14, 0x17:
118
+				recordType = buf[0]
119
+			default:
120
+				return nil, fmt.Errorf("incorrect record type %v", buf[0])
121
+			}
122
+
123
+			if _, err := io.ReadFull(faketls.parent, buf[:]); err != nil {
124
+				return nil, fmt.Errorf("cannot read version: %w", err)
125
+			}
126
+
127
+			if !bytes.Equal(buf[:], []byte{0x03, 0x03}) {
128
+				return nil, fmt.Errorf("unknown tls version %v", buf)
129
+			}
130
+
131
+			if _, err := io.ReadFull(faketls.parent, buf[:]); err != nil {
132
+				return nil, fmt.Errorf("cannot read data length: %w", err)
133
+			}
134
+
135
+			dataLength := binary.BigEndian.Uint16(buf[:])
136
+			if _, err := io.CopyN(data, faketls.parent, int64(dataLength)); err != nil {
137
+				return nil, fmt.Errorf("cannot copy frame data: %w", err)
138
+			}
139
+		}
140
+
141
+		return data.Bytes(), nil
142
+	}
143
+
144
+	return faketls
145
+}

+ 98
- 0
wrappers/stream/rewind.go Просмотреть файл

@@ -0,0 +1,98 @@
1
+package stream
2
+
3
+import (
4
+	"bytes"
5
+	"io"
6
+	"net"
7
+	"sync"
8
+	"time"
9
+
10
+	"go.uber.org/zap"
11
+
12
+	"github.com/9seconds/mtg/conntypes"
13
+)
14
+
15
+type ReadWriteCloseRewinder interface {
16
+	conntypes.StreamReadWriteCloser
17
+	Rewind()
18
+}
19
+
20
+type wrapperRewind struct {
21
+	parent   conntypes.StreamReadWriteCloser
22
+	buf      bytes.Buffer
23
+	mutex    sync.Mutex
24
+	rewinded bool
25
+}
26
+
27
+func (w *wrapperRewind) Write(p []byte) (int, error) {
28
+	return w.parent.Write(p)
29
+}
30
+
31
+func (w *wrapperRewind) WriteTimeout(p []byte, timeout time.Duration) (int, error) {
32
+	return w.parent.WriteTimeout(p, timeout)
33
+}
34
+
35
+func (w *wrapperRewind) Read(p []byte) (int, error) {
36
+	w.mutex.Lock()
37
+	defer w.mutex.Unlock()
38
+
39
+	if w.rewinded {
40
+		if n, err := w.buf.Read(p); err != io.EOF {
41
+			return n, err
42
+		}
43
+	}
44
+
45
+	n, err := w.parent.Read(p)
46
+	w.buf.Write(p[:n])
47
+
48
+	return n, err
49
+}
50
+
51
+func (w *wrapperRewind) ReadTimeout(p []byte, timeout time.Duration) (int, error) {
52
+	w.mutex.Lock()
53
+	defer w.mutex.Unlock()
54
+
55
+	if w.rewinded {
56
+		if n, err := w.buf.Read(p); err != io.EOF {
57
+			return n, err
58
+		}
59
+	}
60
+
61
+	n, err := w.parent.ReadTimeout(p, timeout)
62
+	w.buf.Write(p[:n])
63
+
64
+	return n, err
65
+}
66
+
67
+func (w *wrapperRewind) Conn() net.Conn {
68
+	return w.parent.Conn()
69
+}
70
+
71
+func (w *wrapperRewind) Logger() *zap.SugaredLogger {
72
+	return w.parent.Logger().Named("rewinded")
73
+}
74
+
75
+func (w *wrapperRewind) LocalAddr() *net.TCPAddr {
76
+	return w.parent.LocalAddr()
77
+}
78
+
79
+func (w *wrapperRewind) RemoteAddr() *net.TCPAddr {
80
+	return w.parent.RemoteAddr()
81
+}
82
+
83
+func (w *wrapperRewind) Close() error {
84
+	w.buf.Reset()
85
+	return w.parent.Close()
86
+}
87
+
88
+func (w *wrapperRewind) Rewind() {
89
+	w.mutex.Lock()
90
+	w.rewinded = true
91
+	w.mutex.Unlock()
92
+}
93
+
94
+func NewRewind(parent conntypes.StreamReadWriteCloser) ReadWriteCloseRewinder {
95
+	return &wrapperRewind{
96
+		parent: parent,
97
+	}
98
+}

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