FILE / ScuroNeko/mtg

obfuscated2/client_protocol.go

Исходный файл и его история в репозитории.
FILE 8b802819eecd128ec0b4439423cdcb3a272f47f7
Files
mtg/obfuscated2/client_protocol.go
T

114 lines
3.0 KiB
Go

package obfuscated2
import (
"bytes"
"crypto/sha256"
"encoding/binary"
"errors"
"fmt"
"io"
"time"
"mtg/antireplay"
"mtg/config"
"mtg/conntypes"
"mtg/protocol"
"mtg/stats"
"mtg/utils"
"mtg/wrappers/stream"
)
const clientProtocolHandshakeTimeout = 10 * time.Second
type ClientProtocol struct {
connectionType conntypes.ConnectionType
connectionProtocol conntypes.ConnectionProtocol
dc conntypes.DC
}
func (c *ClientProtocol) ConnectionType() conntypes.ConnectionType {
return c.connectionType
}
func (c *ClientProtocol) ConnectionProtocol() conntypes.ConnectionProtocol {
return c.connectionProtocol
}
func (c *ClientProtocol) DC() conntypes.DC {
return c.dc
}
func (c *ClientProtocol) Handshake(socket conntypes.StreamReadWriteCloser) (conntypes.StreamReadWriteCloser, error) {
fm, err := c.ReadFrame(socket)
if err != nil {
return nil, fmt.Errorf("cannot make a client handshake: %w", err)
}
decHasher := sha256.New()
decHasher.Write(fm.Key()) // nolint: errcheck
decHasher.Write(config.C.Secret) // nolint: errcheck
decryptor := utils.MakeStreamCipher(decHasher.Sum(nil), fm.IV())
invertedFrame := fm.Invert()
encHasher := sha256.New()
encHasher.Write(invertedFrame.Key()) // nolint: errcheck
encHasher.Write(config.C.Secret) // nolint: errcheck
encryptor := utils.MakeStreamCipher(encHasher.Sum(nil), invertedFrame.IV())
decryptedFrame := Frame{}
decryptor.XORKeyStream(decryptedFrame.Bytes(), fm.Bytes())
magic := decryptedFrame.Magic()
switch {
case bytes.Equal(magic, conntypes.ConnectionTagAbridged):
c.connectionType = conntypes.ConnectionTypeAbridged
case bytes.Equal(magic, conntypes.ConnectionTagIntermediate):
c.connectionType = conntypes.ConnectionTypeIntermediate
case bytes.Equal(magic, conntypes.ConnectionTagSecure):
c.connectionType = conntypes.ConnectionTypeSecure
default:
return nil, errors.New("unknown connection type")
}
c.connectionProtocol = conntypes.ConnectionProtocolIPv4
if socket.LocalAddr().IP.To4() == nil {
c.connectionProtocol = conntypes.ConnectionProtocolIPv6
}
buf := bytes.NewReader(decryptedFrame.DC())
if err := binary.Read(buf, binary.LittleEndian, &c.dc); err != nil {
c.dc = conntypes.DCDefaultIdx
}
replayKey := decryptedFrame.Unique()
if antireplay.Cache.HasObfuscated2(replayKey) {
stats.Stats.ReplayDetected()
return nil, errors.New("replay attack is detected")
}
antireplay.Cache.AddObfuscated2(replayKey)
return stream.NewObfuscated2(socket, encryptor, decryptor), nil
}
func (c *ClientProtocol) ReadFrame(socket conntypes.StreamReader) (fm Frame, err error) {
if _, err = io.ReadFull(handshakeReader{socket}, fm.Bytes()); err != nil {
err = fmt.Errorf("cannot extract obfuscated2 frame: %w", err)
}
return
}
type handshakeReader struct {
parent conntypes.StreamReader
}
func (h handshakeReader) Read(p []byte) (int, error) {
return h.parent.ReadTimeout(p, clientProtocolHandshakeTimeout)
}
func MakeClientProtocol() protocol.ClientProtocol {
return &ClientProtocol{}
}