Add required things for middlehandshake

This commit is contained in:
9seconds
2019-09-10 13:54:14 +03:00
parent 691954bd16
commit 1617866c24
6 changed files with 121 additions and 22 deletions
+2 -3
View File
@@ -76,10 +76,9 @@ func Proxy() error {
}()
app := &proxy.Proxy{
Logger: zap.S().Named("proxy"),
Context: ctx,
Logger: zap.S().Named("proxy"),
Context: ctx,
ClientProtocolMaker: obfuscated2.MakeClientProtocol,
TelegramProtocolMaker: obfuscated2.MakeTelegramProtocol,
}
// if len(config.C.AdTag) == 0 {
// app.TelegramProtocolMaker = obfuscated2.MakeTelegramProtocol
+1 -7
View File
@@ -10,9 +10,7 @@ import (
"github.com/9seconds/mtg/wrappers"
)
type TelegramProtocol struct{}
func (t *TelegramProtocol) Handshake(req *protocol.TelegramRequest) (wrappers.Wrap, error) {
func TelegramProtocol(req *protocol.TelegramRequest) (wrappers.Wrap, error) {
socket, err := telegram.Direct.Dial(req.Ctx,
req.Cancel,
req.ClientProtocol.DC(),
@@ -39,10 +37,6 @@ func (t *TelegramProtocol) Handshake(req *protocol.TelegramRequest) (wrappers.Wr
return wrappers.NewObfuscated2(socket, encryptor, decryptor), nil
}
func MakeTelegramProtocol() protocol.TelegramProtocol {
return &TelegramProtocol{}
}
func generateFrame(cp protocol.ClientProtocol) (fm Frame) {
data := fm.Bytes()
+1 -5
View File
@@ -12,9 +12,5 @@ type ClientProtocol interface {
DC() conntypes.DC
}
type TelegramProtocol interface {
Handshake(*TelegramRequest) (wrappers.Wrap, error)
}
type TelegramProtocol func(*TelegramRequest) (wrappers.Wrap, error)
type ClientProtocolMaker func() ClientProtocol
type TelegramProtocolMaker func() TelegramProtocol
+5 -6
View File
@@ -10,6 +10,7 @@ import (
"github.com/9seconds/mtg/config"
"github.com/9seconds/mtg/conntypes"
"github.com/9seconds/mtg/obfuscated2"
"github.com/9seconds/mtg/protocol"
"github.com/9seconds/mtg/stats"
"github.com/9seconds/mtg/utils"
@@ -19,10 +20,9 @@ import (
const directPipeBufferSize = 1024 * 1024
type Proxy struct {
Logger *zap.SugaredLogger
Context context.Context
ClientProtocolMaker protocol.ClientProtocolMaker
TelegramProtocolMaker protocol.TelegramProtocolMaker
Logger *zap.SugaredLogger
Context context.Context
ClientProtocolMaker protocol.ClientProtocolMaker
}
func (p *Proxy) Serve(listener net.Listener) {
@@ -98,8 +98,7 @@ func (p *Proxy) accept(conn net.Conn) {
}
func (p *Proxy) acceptDirectConnection(request *protocol.TelegramRequest) error {
telegramProtocol := p.TelegramProtocolMaker()
telegramConnRaw, err := telegramProtocol.Handshake(request)
telegramConnRaw, err := obfuscated2.TelegramProtocol(request)
if err != nil {
return err
}
+1 -1
View File
@@ -148,7 +148,7 @@ func (w *wrapperBlockCipher) RemoteAddr() *net.TCPAddr {
return w.parent.RemoteAddr()
}
func NewBlockCipher(parent StreamReadWriteCloser, encryptor, decryptor cipher.BlockMode) StreamReadWriteCloser {
func newBlockCipher(parent StreamReadWriteCloser, encryptor, decryptor cipher.BlockMode) StreamReadWriteCloser {
return &wrapperBlockCipher{
parent: parent,
encryptor: encryptor,
+111
View File
@@ -0,0 +1,111 @@
package wrappers
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/md5"
"crypto/sha1"
"encoding/binary"
"net"
"github.com/9seconds/mtg/mtproto/rpc"
"github.com/9seconds/mtg/utils"
)
type mtprotoCipherPurpose uint8
const (
mtprotoCipherPurposeClient mtprotoCipherPurpose = iota
mtprotoCipherPurposeServer
)
var mtprotoEmptyIP = [4]byte{0x00, 0x00, 0x00, 0x00}
func NewMiddleProxyCipher(parent StreamReadWriteCloser,
req *rpc.NonceRequest,
resp *rpc.NonceResponse,
secret []byte) StreamReadWriteCloser {
localAddr := parent.LocalAddr()
remoteAddr := parent.RemoteAddr()
encKey, encIV := mtprotoDeriveKeys(mtprotoCipherPurposeClient,
req,
resp,
localAddr,
remoteAddr,
secret)
decKey, decIV := mtprotoDeriveKeys(mtprotoCipherPurposeServer,
req,
resp,
localAddr,
remoteAddr,
secret)
enc, _ := mtprotoMakeEncrypterDecrypter(encKey, encIV)
_, dec := mtprotoMakeEncrypterDecrypter(decKey, decIV)
return newBlockCipher(parent, enc, dec)
}
func mtprotoDeriveKeys(purpose mtprotoCipherPurpose,
req *rpc.NonceRequest,
resp *rpc.NonceResponse,
client, remote *net.TCPAddr,
secret []byte) ([]byte, []byte) {
message := bytes.Buffer{}
message.Write(resp.Nonce) // nolint: gosec
message.Write(req.Nonce) // nolint: gosec
message.Write(req.CryptoTS) // nolint: gosec
clientIPv4 := mtprotoEmptyIP[:]
serverIPv4 := mtprotoEmptyIP[:]
if client.IP.To4() != nil {
clientIPv4 = utils.ReverseBytes(client.IP.To4())
serverIPv4 = utils.ReverseBytes(remote.IP.To4())
}
message.Write(serverIPv4) // nolint: gosec
var port [2]byte
binary.LittleEndian.PutUint16(port[:], uint16(client.Port))
message.Write(port[:]) // nolint: gosec
switch purpose {
case mtprotoCipherPurposeClient:
message.WriteString("CLIENT") // nolint: gosec
case mtprotoCipherPurposeServer:
message.WriteString("SERVER") // nolint: gosec
default:
panic("Unexpected cipher purpose")
}
message.Write(clientIPv4) // nolint: gosec
binary.LittleEndian.PutUint16(port[:], uint16(remote.Port))
message.Write(port[:]) // nolint: gosec
message.Write(secret) // nolint: gosec
message.Write(resp.Nonce) // nolint: gosec
if client.IP.To4() == nil {
message.Write(client.IP.To16()) // nolint: gosec
message.Write(remote.IP.To16()) // nolint: gosec
}
message.Write(req.Nonce) // nolint: gosec
data := message.Bytes()
md5sum := md5.Sum(data[1:]) // nolint: gas
sha1sum := sha1.Sum(data) // nolint: gosec
key := append(md5sum[:12], sha1sum[:]...)
iv := md5.Sum(data[2:]) // nolint: gas
return key, iv[:]
}
func mtprotoMakeEncrypterDecrypter(key, iv []byte) (cipher.BlockMode, cipher.BlockMode) {
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
return cipher.NewCBCEncrypter(block, iv), cipher.NewCBCDecrypter(block, iv)
}