9seconds 7 лет назад
Родитель
Сommit
4262e5f5de
4 измененных файлов: 143 добавлений и 180 удалений
  1. 0
    48
      mtproto/wrappers/crypt_test.go
  2. 0
    111
      mtproto/wrappers/proxy_request.go
  3. 8
    21
      wrappers/mtproto_cipher.go
  4. 135
    0
      wrappers/mtproto_proxy.go

+ 0
- 48
mtproto/wrappers/crypt_test.go Просмотреть файл

@@ -1,48 +0,0 @@
1
-package wrappers
2
-
3
-import (
4
-	"encoding/binary"
5
-	"net"
6
-	"testing"
7
-
8
-	"github.com/stretchr/testify/assert"
9
-
10
-	"github.com/9seconds/mtg/mtproto/rpc"
11
-)
12
-
13
-var proxySecret = []byte{196, 249, 250, 202, 150, 120, 230, 187, 72, 173,
14
-	108, 126, 44, 229, 192, 210, 68, 48, 100, 93, 85, 74, 221, 235, 85, 65,
15
-	158, 3, 77, 166, 39, 33, 208, 70, 234, 171, 110, 82, 171, 20, 169, 90, 68,
16
-	62, 207, 179, 70, 62, 121, 160, 90, 102, 97, 42, 223, 156, 174, 218, 139,
17
-	233, 168, 13, 166, 152, 111, 176, 166, 255, 56, 122, 248, 77, 136, 239,
18
-	58, 100, 19, 113, 62, 92, 51, 119, 246, 225, 163, 212, 125, 153, 245, 224,
19
-	197, 110, 236, 232, 240, 92, 84, 196, 144, 176, 121, 227, 27, 239, 130,
20
-	255, 14, 232, 242, 176, 163, 39, 86, 210, 73, 197, 242, 18, 105, 129, 108,
21
-	183, 6, 27, 38, 93, 178, 18}
22
-
23
-func TestMakeKeys(t *testing.T) {
24
-	req, err := rpc.NewNonceRequest(proxySecret)
25
-	assert.Nil(t, err)
26
-
27
-	copy(req.Nonce[:], []byte{24, 49, 53, 111, 198, 10, 235, 180, 230, 112, 92, 78, 1, 201, 106, 105})
28
-	binary.LittleEndian.PutUint32(req.CryptoTS[:], 1528396015)
29
-
30
-	resp := &rpc.NonceResponse{
31
-		NonceRequest: rpc.NonceRequest{
32
-			Nonce: []byte{247, 40, 210, 56, 65, 12, 101, 170, 216, 155, 14, 253, 250, 238, 219, 226},
33
-		},
34
-	}
35
-
36
-	cltAddr := &net.TCPAddr{
37
-		IP:   net.ParseIP("80.211.29.34"),
38
-		Port: 54208,
39
-	}
40
-	srvAddr := &net.TCPAddr{
41
-		IP:   net.ParseIP("149.154.162.38"),
42
-		Port: 80,
43
-	}
44
-
45
-	key, iv := makeKeys(CipherPurposeClient, req, resp, cltAddr, srvAddr, proxySecret)
46
-	assert.Equal(t, key, []byte{165, 158, 127, 49, 41, 232, 187, 69, 38, 29, 163, 226, 183, 146, 28, 67, 225, 224, 134, 191, 207, 152, 255, 166, 152, 66, 169, 196, 54, 135, 50, 188})
47
-	assert.Equal(t, iv, []byte{33, 110, 125, 221, 183, 121, 160, 116, 130, 180, 156, 249, 52, 111, 37, 178})
48
-}

+ 0
- 111
mtproto/wrappers/proxy_request.go Просмотреть файл

@@ -1,111 +0,0 @@
1
-package wrappers
2
-
3
-import (
4
-	"bytes"
5
-	"io"
6
-	"io/ioutil"
7
-	"net"
8
-
9
-	"github.com/juju/errors"
10
-
11
-	"github.com/9seconds/mtg/mtproto"
12
-	"github.com/9seconds/mtg/mtproto/rpc"
13
-	"github.com/9seconds/mtg/utils"
14
-	"github.com/9seconds/mtg/wrappers"
15
-)
16
-
17
-type ProxyRequestReadWriteCloserWithAddr struct {
18
-	wrappers.BufferedReader
19
-
20
-	conn wrappers.ReadWriteCloserWithAddr
21
-	req  *rpc.ProxyRequest
22
-}
23
-
24
-func (p *ProxyRequestReadWriteCloserWithAddr) Read(buf []byte) (int, error) {
25
-	return p.BufferedRead(buf, func() error {
26
-		ans := make([]byte, 4)
27
-		if _, err := io.ReadFull(p.conn, ans); err != nil {
28
-			return errors.Annotate(err, "Cannot read RPC tag")
29
-		}
30
-
31
-		switch {
32
-		case bytes.Equal(ans, rpc.TagProxyAns):
33
-			return p.readProxyAns()
34
-		case bytes.Equal(ans, rpc.TagSimpleAck):
35
-			return p.readSimpleAck()
36
-		case bytes.Equal(ans, rpc.TagCloseExt):
37
-			return p.readCloseExt()
38
-		}
39
-
40
-		return errors.Errorf("Unknown RPC answer %v", ans)
41
-	})
42
-}
43
-
44
-func (p *ProxyRequestReadWriteCloserWithAddr) readCloseExt() error {
45
-	return errors.New("Connection has been closed remotely")
46
-}
47
-
48
-func (p *ProxyRequestReadWriteCloserWithAddr) readProxyAns() (err error) {
49
-	if _, err = io.CopyN(ioutil.Discard, p.conn, 8+4); err != nil {
50
-		return errors.Annotate(err, "Cannot skip flags and connid")
51
-	}
52
-
53
-	buf, err := utils.ReadCurrentData(p.conn)
54
-	if err != nil {
55
-		return errors.Annotate(err, "Cannot read proxy answer")
56
-	}
57
-	p.Buffer.Write(buf)
58
-
59
-	return nil
60
-}
61
-
62
-func (p *ProxyRequestReadWriteCloserWithAddr) readSimpleAck() error {
63
-	if _, err := io.CopyN(ioutil.Discard, p.conn, 8); err != nil {
64
-		return errors.Annotate(err, "Cannot skip connid")
65
-	}
66
-
67
-	ackData := make([]byte, 4)
68
-	if _, err := io.ReadFull(p.conn, ackData); err != nil {
69
-		return errors.Annotate(err, "Cannot read simple ack")
70
-	}
71
-	p.Buffer.Write(ackData)
72
-
73
-	return nil
74
-}
75
-
76
-func (p *ProxyRequestReadWriteCloserWithAddr) Write(raw []byte) (int, error) {
77
-	if _, err := p.conn.Write(p.req.Bytes(raw)); err != nil {
78
-		return 0, err
79
-	}
80
-
81
-	return len(raw), nil
82
-}
83
-
84
-func (p *ProxyRequestReadWriteCloserWithAddr) Close() error {
85
-	return p.conn.Close()
86
-}
87
-
88
-func (p *ProxyRequestReadWriteCloserWithAddr) LocalAddr() *net.TCPAddr {
89
-	return p.conn.LocalAddr()
90
-}
91
-
92
-func (p *ProxyRequestReadWriteCloserWithAddr) RemoteAddr() *net.TCPAddr {
93
-	return p.conn.RemoteAddr()
94
-}
95
-
96
-func (p *ProxyRequestReadWriteCloserWithAddr) SocketID() string {
97
-	return p.conn.SocketID()
98
-}
99
-
100
-func NewProxyRequestRWC(conn wrappers.ReadWriteCloserWithAddr, connOpts *mtproto.ConnectionOpts, adTag []byte) (wrappers.ReadWriteCloserWithAddr, error) {
101
-	req, err := rpc.NewProxyRequest(connOpts.ClientAddr, conn.LocalAddr(), connOpts, adTag)
102
-	if err != nil {
103
-		return nil, errors.Annotate(err, "Cannot create new RPC proxy request")
104
-	}
105
-
106
-	return &ProxyRequestReadWriteCloserWithAddr{
107
-		BufferedReader: wrappers.NewBufferedReader(),
108
-		conn:           conn,
109
-		req:            req,
110
-	}, nil
111
-}

mtproto/wrappers/crypt.go → wrappers/mtproto_cipher.go Просмотреть файл

@@ -10,7 +10,7 @@ import (
10 10
 	"net"
11 11
 
12 12
 	"github.com/9seconds/mtg/mtproto/rpc"
13
-	"github.com/9seconds/mtg/wrappers"
13
+	"github.com/9seconds/mtg/utils"
14 14
 )
15 15
 
16 16
 type CipherPurpose uint8
@@ -22,20 +22,20 @@ const (
22 22
 
23 23
 var emptyIP = [4]byte{0x00, 0x00, 0x00, 0x00}
24 24
 
25
-func NewMiddleProxyCipherRWC(conn wrappers.ReadWriteCloserWithAddr, req *rpc.NonceRequest, resp *rpc.NonceResponse, secret []byte) wrappers.ReadWriteCloserWithAddr {
25
+func NewMiddleProxyCipher(conn WrapStreamReadWriteCloser, req *rpc.NonceRequest, resp *rpc.NonceResponse, secret []byte) WrapStreamReadWriteCloser {
26 26
 	localAddr := conn.LocalAddr()
27 27
 	remoteAddr := conn.RemoteAddr()
28 28
 
29
-	encKey, encIV := makeKeys(CipherPurposeClient, req, resp, localAddr, remoteAddr, secret)
30
-	decKey, decIV := makeKeys(CipherPurposeServer, req, resp, localAddr, remoteAddr, secret)
29
+	encKey, encIV := deriveKeys(CipherPurposeClient, req, resp, localAddr, remoteAddr, secret)
30
+	decKey, decIV := deriveKeys(CipherPurposeServer, req, resp, localAddr, remoteAddr, secret)
31 31
 
32 32
 	enc, _ := makeEncrypterDecrypter(encKey, encIV)
33 33
 	_, dec := makeEncrypterDecrypter(decKey, decIV)
34 34
 
35
-	return wrappers.NewBlockCipherRWC(conn, enc, dec)
35
+	return NewWrapBlockCipher(conn, enc, dec)
36 36
 }
37 37
 
38
-func makeKeys(purpose CipherPurpose, req *rpc.NonceRequest, resp *rpc.NonceResponse, client *net.TCPAddr, remote *net.TCPAddr, secret []byte) ([]byte, []byte) {
38
+func deriveKeys(purpose CipherPurpose, req *rpc.NonceRequest, resp *rpc.NonceResponse, client *net.TCPAddr, remote *net.TCPAddr, secret []byte) ([]byte, []byte) {
39 39
 	message := bytes.Buffer{}
40 40
 	message.Write(resp.Nonce[:])
41 41
 	message.Write(req.Nonce[:])
@@ -44,8 +44,8 @@ func makeKeys(purpose CipherPurpose, req *rpc.NonceRequest, resp *rpc.NonceRespo
44 44
 	clientIPv4 := emptyIP[:]
45 45
 	serverIPv4 := emptyIP[:]
46 46
 	if client.IP.To4() != nil {
47
-		clientIPv4 = reverseBytes(client.IP.To4())
48
-		serverIPv4 = reverseBytes(remote.IP.To4())
47
+		clientIPv4 = utils.ReverseBytes(client.IP.To4())
48
+		serverIPv4 = utils.ReverseBytes(remote.IP.To4())
49 49
 	}
50 50
 	message.Write(serverIPv4)
51 51
 
@@ -92,16 +92,3 @@ func makeEncrypterDecrypter(key, iv []byte) (cipher.BlockMode, cipher.BlockMode)
92 92
 
93 93
 	return cipher.NewCBCEncrypter(block, iv), cipher.NewCBCDecrypter(block, iv)
94 94
 }
95
-
96
-func reverseBytes(data []byte) []byte {
97
-	dataLen := len(data)
98
-	rv := make([]byte, dataLen)
99
-
100
-	rv[dataLen/2] = data[dataLen/2]
101
-	for i := dataLen/2 - 1; i >= 0; i-- {
102
-		opp := dataLen - i - 1
103
-		rv[i], rv[opp] = data[opp], data[i]
104
-	}
105
-
106
-	return rv
107
-}

+ 135
- 0
wrappers/mtproto_proxy.go Просмотреть файл

@@ -0,0 +1,135 @@
1
+package wrappers
2
+
3
+import (
4
+	"bytes"
5
+	"net"
6
+
7
+	"github.com/9seconds/mtg/mtproto/rpc"
8
+	"github.com/juju/errors"
9
+)
10
+
11
+type MTProtoProxy struct {
12
+	conn WrapPacketReadWriteCloser
13
+	req  *rpc.ProxyRequest
14
+
15
+	readCounter  uint32
16
+	writeCounter uint32
17
+}
18
+
19
+func (m *MTProtoProxy) Read() ([]byte, error) {
20
+	m.LogDebug("Read packet",
21
+		"counter", m.readCounter,
22
+		"simple_ack", m.req.Options.WriteHacks.SimpleAck,
23
+		"quick_ack", m.req.Options.WriteHacks.QuickAck,
24
+	)
25
+
26
+	packet, err := m.conn.Read()
27
+	if err != nil {
28
+		return nil, errors.Annotate(err, "Cannot read packet")
29
+	}
30
+	m.LogDebug("Read packet length",
31
+		"counter", m.readCounter,
32
+		"simple_ack", m.req.Options.WriteHacks.SimpleAck,
33
+		"quick_ack", m.req.Options.WriteHacks.QuickAck,
34
+		"length", len(packet),
35
+	)
36
+
37
+	if len(packet) < 4 {
38
+		return nil, errors.Annotate(err, "Incorrect packet length")
39
+	}
40
+
41
+	tag, packet := packet[:4], packet[4:]
42
+	m.LogDebug("Read RPC tag",
43
+		"counter", m.readCounter,
44
+		"simple_ack", m.req.Options.WriteHacks.SimpleAck,
45
+		"quick_ack", m.req.Options.WriteHacks.QuickAck,
46
+		"tag", tag,
47
+	)
48
+
49
+	m.readCounter++
50
+	switch {
51
+	case bytes.Equal(tag, rpc.TagProxyAns):
52
+		return m.readProxyAns(packet)
53
+	case bytes.Equal(tag, rpc.TagSimpleAck):
54
+		return m.readSimpleAck(packet)
55
+	case bytes.Equal(tag, rpc.TagCloseExt):
56
+		return m.readCloseExt(packet)
57
+	}
58
+
59
+	return nil, errors.Errorf("Unknown RPC answer %v", tag)
60
+}
61
+
62
+func (m *MTProtoProxy) readProxyAns(data []byte) ([]byte, error) {
63
+	if len(data) < 12 {
64
+		return nil, errors.Errorf("Incorrect data of proxy answer: %d", len(data))
65
+	}
66
+
67
+	return data[12:], nil
68
+}
69
+
70
+func (m *MTProtoProxy) readSimpleAck(data []byte) ([]byte, error) {
71
+	if len(data) != 12 {
72
+		return nil, errors.Errorf("Incorrect data of simple ack: %d", len(data))
73
+	}
74
+
75
+	return data[8:12], nil // 0:8 - connection id
76
+}
77
+
78
+func (m *MTProtoProxy) readCloseExt(data []byte) ([]byte, error) {
79
+	return nil, errors.New("Connection has been closed remotely by RPC call")
80
+}
81
+
82
+func (m *MTProtoProxy) Write(p []byte) (int, error) {
83
+	m.LogDebug("Write packet",
84
+		"length", len(p),
85
+		"counter", m.writeCounter,
86
+		"simple_ack", m.req.Options.ReadHacks.SimpleAck,
87
+		"quick_ack", m.req.Options.ReadHacks.QuickAck,
88
+	)
89
+	m.writeCounter++
90
+
91
+	if _, err := m.conn.Write(p); err != nil {
92
+		return 0, err
93
+	}
94
+
95
+	return len(p), nil
96
+}
97
+
98
+func (m *MTProtoProxy) LogDebug(msg string, data ...interface{}) {
99
+	data = append(data, []interface{}{"type", "proxy"})
100
+	m.conn.LogDebug(msg, data...)
101
+}
102
+
103
+func (m *MTProtoProxy) LogInfo(msg string, data ...interface{}) {
104
+	data = append(data, []interface{}{"type", "proxy"})
105
+	m.conn.LogInfo(msg, data...)
106
+}
107
+
108
+func (m *MTProtoProxy) LogWarn(msg string, data ...interface{}) {
109
+	data = append(data, []interface{}{"type", "proxy"})
110
+	m.conn.LogWarn(msg, data...)
111
+}
112
+
113
+func (m *MTProtoProxy) LogError(msg string, data ...interface{}) {
114
+	data = append(data, []interface{}{"type", "proxy"})
115
+	m.conn.LogError(msg, data...)
116
+}
117
+
118
+func (m *MTProtoProxy) LocalAddr() *net.TCPAddr {
119
+	return m.conn.LocalAddr()
120
+}
121
+
122
+func (m *MTProtoProxy) RemoteAddr() *net.TCPAddr {
123
+	return m.conn.RemoteAddr()
124
+}
125
+
126
+func (m *MTProtoProxy) Close() error {
127
+	return m.conn.Close()
128
+}
129
+
130
+func NewMTProtoProxy(conn WrapPacketReadWriteCloser, req *rpc.ProxyRequest) WrapPacketReadWriteCloser {
131
+	return &MTProtoProxy{
132
+		conn: conn,
133
+		req:  req,
134
+	}
135
+}

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