mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-08-31 10:44:02 +03:00
Add tests for obfuscated2 clientside
This commit is contained in:
@@ -30,8 +30,6 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
go_version:
|
||||
- ~1.14
|
||||
- ~1.15
|
||||
- ^1.16
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
||||
+2
-3
@@ -5,7 +5,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -123,11 +122,11 @@ func (c *Access) getIP(protocol string) net.IP {
|
||||
}
|
||||
|
||||
defer func() {
|
||||
io.Copy(ioutil.Discard, resp.Body) // nolint: errcheck
|
||||
io.Copy(io.Discard, resp.Body) // nolint: errcheck
|
||||
resp.Body.Close()
|
||||
}()
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
+2
-2
@@ -2,9 +2,9 @@ package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
|
||||
"github.com/9seconds/mtg/v2/config"
|
||||
"github.com/9seconds/mtg/v2/mtglib"
|
||||
@@ -19,7 +19,7 @@ type base struct {
|
||||
}
|
||||
|
||||
func (b *base) ReadConfig(version string) error {
|
||||
content, err := ioutil.ReadFile(b.ConfigPath)
|
||||
content, err := os.ReadFile(b.ConfigPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot read config file: %w", err)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package config_test
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
@@ -14,7 +14,7 @@ type ConfigTestSuite struct {
|
||||
}
|
||||
|
||||
func (suite *ConfigTestSuite) ReadConfig(filename string) []byte {
|
||||
data, err := ioutil.ReadFile(filepath.Join("testdata", filename))
|
||||
data, err := os.ReadFile(filepath.Join("testdata", filename))
|
||||
suite.NoError(err)
|
||||
|
||||
return data
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -216,7 +215,7 @@ func (f *Firehol) updateRemoteURL(ctx context.Context, url string,
|
||||
}(ctx, resp.Body)
|
||||
|
||||
defer func(rc io.ReadCloser) {
|
||||
io.Copy(ioutil.Discard, rc) // nolint: errcheck
|
||||
io.Copy(io.Discard, rc) // nolint: errcheck
|
||||
rc.Close()
|
||||
}(resp.Body)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
func ClientHandshake(secret []byte, reader io.Reader) (int16, cipher.Stream, cipher.Stream, error) {
|
||||
func ClientHandshake(secret []byte, reader io.Reader) (int, cipher.Stream, cipher.Stream, error) {
|
||||
handshake := clientHandhakeFrame{}
|
||||
|
||||
if _, err := io.ReadFull(reader, handshake.data[:]); err != nil {
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package obfuscated2_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/9seconds/mtg/v2/mtglib/internal/obfuscated2"
|
||||
"github.com/9seconds/mtg/v2/testlib"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type ClientHandshakeTestSuite struct {
|
||||
suite.Suite
|
||||
SnapshotTestSuite
|
||||
}
|
||||
|
||||
func (suite *ClientHandshakeTestSuite) SetupSuite() {
|
||||
suite.NoError(suite.IngestSnapshots("client_snapshots", "snapshot-ok-"))
|
||||
}
|
||||
|
||||
func (suite *ClientHandshakeTestSuite) TestCannotRead() {
|
||||
buf := bytes.NewBuffer([]byte{1, 2, 3})
|
||||
_, _, _, err := obfuscated2.ClientHandshake([]byte{1, 2, 3}, buf) // nolint: dogsled
|
||||
|
||||
suite.Error(err)
|
||||
}
|
||||
|
||||
func (suite *ClientHandshakeTestSuite) TestOk() {
|
||||
for nameV, snapshotV := range suite.snapshots {
|
||||
snapshot := snapshotV
|
||||
|
||||
suite.T().Run(nameV, func(t *testing.T) {
|
||||
buf := bytes.NewBuffer(snapshot.Frame.data)
|
||||
|
||||
dc, encryptor, decryptor, err := obfuscated2.ClientHandshake(
|
||||
snapshot.Secret.data, buf)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, snapshot.DC, dc)
|
||||
|
||||
writeData := make([]byte, len(snapshot.Encrypted.Text.data))
|
||||
readData := make([]byte, len(snapshot.Decrypted.Text.data))
|
||||
|
||||
connMock := &testlib.NetConnMock{}
|
||||
connMock.On("Read", mock.Anything).
|
||||
Once().
|
||||
Return(len(snapshot.Decrypted.Text.data), nil).
|
||||
Run(func(args mock.Arguments) {
|
||||
arr := args.Get(0).([]byte)
|
||||
copy(arr, snapshot.Decrypted.Cipher.data)
|
||||
})
|
||||
connMock.On("Write", mock.Anything).
|
||||
Once().
|
||||
Return(len(snapshot.Encrypted.Text.data), nil).
|
||||
Run(func(args mock.Arguments) {
|
||||
arr := args.Get(0).([]byte)
|
||||
copy(writeData, arr)
|
||||
})
|
||||
|
||||
conn := &obfuscated2.Conn{
|
||||
Conn: connMock,
|
||||
Encryptor: encryptor,
|
||||
Decryptor: decryptor,
|
||||
}
|
||||
|
||||
n, err := conn.Read(readData)
|
||||
assert.Equal(t, len(readData), n)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, snapshot.Decrypted.Text.data, readData)
|
||||
|
||||
n, err = conn.Write(snapshot.Encrypted.Text.data)
|
||||
assert.Equal(t, len(writeData), n)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, snapshot.Encrypted.Cipher.data, writeData)
|
||||
|
||||
connMock.AssertExpectations(t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientHandshake(t *testing.T) {
|
||||
t.Parallel()
|
||||
suite.Run(t, &ClientHandshakeTestSuite{})
|
||||
}
|
||||
@@ -35,10 +35,18 @@ type handshakeFrame struct {
|
||||
data [handshakeFrameLen]byte
|
||||
}
|
||||
|
||||
func (h *handshakeFrame) dc() int16 {
|
||||
func (h *handshakeFrame) dc() int {
|
||||
data := h.data[handshakeFrameOffsetDC:handshakeFrameOffsetEnd]
|
||||
idx := int16(binary.LittleEndian.Uint16(data))
|
||||
|
||||
return int16(binary.LittleEndian.Uint16(data))
|
||||
switch {
|
||||
case idx > 0:
|
||||
return int(idx) - 1
|
||||
case idx < 0:
|
||||
return -int(idx + 1)
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handshakeFrame) key() []byte {
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
package obfuscated2_test
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type snapshotBytes struct {
|
||||
data []byte
|
||||
}
|
||||
|
||||
func (s snapshotBytes) MarshalText() ([]byte, error) {
|
||||
if len(s.data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return []byte(base64.RawStdEncoding.EncodeToString(s.data)), nil
|
||||
}
|
||||
|
||||
func (s *snapshotBytes) UnmarshalText(data []byte) error {
|
||||
val, err := base64.RawStdEncoding.DecodeString(string(data))
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot unmarshal %v: %w", len(val), err)
|
||||
}
|
||||
|
||||
s.data = val
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type Obfuscated2Snapshot struct {
|
||||
Secret snapshotBytes `json:"secret"`
|
||||
Frame snapshotBytes `json:"frame"`
|
||||
DC int16 `json:"dc"`
|
||||
Encrypted struct {
|
||||
Text snapshotBytes `json:"text"`
|
||||
Cipher snapshotBytes `json:"cipher"`
|
||||
} `json:"encrypted"`
|
||||
Decrypted struct {
|
||||
Text snapshotBytes `json:"text"`
|
||||
Cipher snapshotBytes `json:"cipher"`
|
||||
} `json:"decrypted"`
|
||||
}
|
||||
|
||||
type SnapshotTestSuite struct {
|
||||
snapshots map[string]*Obfuscated2Snapshot
|
||||
}
|
||||
|
||||
func (suite *SnapshotTestSuite) IngestSnapshots(dirname, namePrefix string) error {
|
||||
suite.snapshots = map[string]*Obfuscated2Snapshot{}
|
||||
|
||||
files, err := os.ReadDir(filepath.Join("testdata", dirname))
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot ingest snapshots: %w", err)
|
||||
}
|
||||
|
||||
for _, v := range files {
|
||||
if !strings.HasPrefix(v.Name(), namePrefix) {
|
||||
continue
|
||||
}
|
||||
|
||||
filename := filepath.Join("testdata", dirname, v.Name())
|
||||
|
||||
contents, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot read %s: %w", filename, err)
|
||||
}
|
||||
|
||||
value := &Obfuscated2Snapshot{}
|
||||
|
||||
if err := json.Unmarshal(contents, value); err != nil {
|
||||
return fmt.Errorf("cannot unmarshal %s: %w", filename, err)
|
||||
}
|
||||
|
||||
suite.snapshots[v.Name()] = value
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"secret": "NnoYmu4Y+jHBkAVO/UqOlQ",
|
||||
"frame": "gDcXwaMY4RwlR+nJw+ILDr123UJHHjjE/U5pF4m/Y04AmH7lEpEL6UYRnIYDbDlOHSDxc1ToziPvNlJJh8RMow",
|
||||
"dc": 1,
|
||||
"encrypted": {
|
||||
"text": "AQIDBAUGBwgJCg",
|
||||
"cipher": "wZV3TR39l9nRoQ"
|
||||
},
|
||||
"decrypted": {
|
||||
"text": "4wZj6mUUew",
|
||||
"cipher": "YWJjZGVmZw"
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"secret": "NnoYmu4Y+jHBkAVO/UqOlQ",
|
||||
"frame": "M2WyxeiwIQB+ZOFxNzSNHtu9OdESkfxv3JkKFimCxUoYA3BD/Ql9nXB/OIonCKLUKCcS0VzZ2P6/+5oQ9GI8YA",
|
||||
"dc": 1,
|
||||
"encrypted": {
|
||||
"text": "AQIDBAUGBwgJCg",
|
||||
"cipher": "tzAwrCz00odERg"
|
||||
},
|
||||
"decrypted": {
|
||||
"text": "QkIvwGQDgA",
|
||||
"cipher": "YWJjZGVmZw"
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"secret": "NnoYmu4Y+jHBkAVO/UqOlQ",
|
||||
"frame": "ZEZY1K3SZZgHX2MgMeYMMVoIPYR6eP+bgKxjI7IHl6sPLhfH2jRitS7/VA6Kz8E2L+uLqVom7x4zO+D5Q5iARA",
|
||||
"dc": 1,
|
||||
"encrypted": {
|
||||
"text": "AQIDBAUGBwgJCg",
|
||||
"cipher": "WptF2u4ZSDMZxQ"
|
||||
},
|
||||
"decrypted": {
|
||||
"text": "DT+Ob9yGWA",
|
||||
"cipher": "YWJjZGVmZw"
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"secret": "NnoYmu4Y+jHBkAVO/UqOlQ",
|
||||
"frame": "/rbO1fCVLR7o28nrc9inrdDU+4Z4uOqbC2kMnNnzItv0fJmn4hcUXK6YBJQZVI01i7rFlgiCtTgrHtyfQp9p9w",
|
||||
"dc": 1,
|
||||
"encrypted": {
|
||||
"text": "AQIDBAUGBwgJCg",
|
||||
"cipher": "jKZzALBemf72Cw"
|
||||
},
|
||||
"decrypted": {
|
||||
"text": "fMOlRiN20A",
|
||||
"cipher": "YWJjZGVmZw"
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"secret": "NnoYmu4Y+jHBkAVO/UqOlQ",
|
||||
"frame": "SfqaPWt1F8WTfrTkTl06s7F1nUcBR6AUp5uniCcYpVCJvgYpOO3TQHUZbLaFbI5qYRjJBQDe9OpXDJjR/5z4lg",
|
||||
"dc": 1,
|
||||
"encrypted": {
|
||||
"text": "AQIDBAUGBwgJCg",
|
||||
"cipher": "0DtHeQPN2bv7Qw"
|
||||
},
|
||||
"decrypted": {
|
||||
"text": "BWPiYKe4bA",
|
||||
"cipher": "YWJjZGVmZw"
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"secret": "NnoYmu4Y+jHBkAVO/UqOlQ",
|
||||
"frame": "MF6BfhvxyI61vFHZN/ecrDF1sZux/JdgVjKX1Yzy7SmBhYu+8bS25ta8iFsj/4y2moBpeNFp7rqekCE3FRb29A",
|
||||
"dc": 1,
|
||||
"encrypted": {
|
||||
"text": "AQIDBAUGBwgJCg",
|
||||
"cipher": "MujITanGx9xf9g"
|
||||
},
|
||||
"decrypted": {
|
||||
"text": "0xVTx0JKug",
|
||||
"cipher": "YWJjZGVmZw"
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"secret": "NnoYmu4Y+jHBkAVO/UqOlQ",
|
||||
"frame": "YY3y0amcDqggxeNbnyyacKl++b3Q7X0XL9coxctXxJOYZQ/uXIaWFm1KD3s0VIKQ6C7NqJ8hnnJOcpp2Bdau6A",
|
||||
"dc": 1,
|
||||
"encrypted": {
|
||||
"text": "AQIDBAUGBwgJCg",
|
||||
"cipher": "mni7eHb24tufLQ"
|
||||
},
|
||||
"decrypted": {
|
||||
"text": "Aqi/2cgHXA",
|
||||
"cipher": "YWJjZGVmZw"
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"secret": "NnoYmu4Y+jHBkAVO/UqOlQ",
|
||||
"frame": "k0f9Sv7V7svvxmHlIP4Ajg0sTGb0NXHfJDk1h6VgAnV0my1F+NU8KPG35kqXC9IDQZK/6fOABb7npO8/TCHEzQ",
|
||||
"dc": 1,
|
||||
"encrypted": {
|
||||
"text": "AQIDBAUGBwgJCg",
|
||||
"cipher": "efUzYxRvqEYPlw"
|
||||
},
|
||||
"decrypted": {
|
||||
"text": "FFPwzZkL2A",
|
||||
"cipher": "YWJjZGVmZw"
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"secret": "NnoYmu4Y+jHBkAVO/UqOlQ",
|
||||
"frame": "NiK5AnDAJw+fsytYBnxOmcDl6jx3uQECznBS4WIaHXGWP0tcioPikE1mVtkp33aXT7bCfFlst+b0PvcldGSARw",
|
||||
"dc": 1,
|
||||
"encrypted": {
|
||||
"text": "AQIDBAUGBwgJCg",
|
||||
"cipher": "56aF+oauHVDbPQ"
|
||||
},
|
||||
"decrypted": {
|
||||
"text": "KycK+00LvQ",
|
||||
"cipher": "YWJjZGVmZw"
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"secret": "NnoYmu4Y+jHBkAVO/UqOlQ",
|
||||
"frame": "nYvAavvf0TywZ4hkfGEgf6ZmnIUsDWjRKzLktqF65D+3ha/LqViPdpvsexguXBd5HClDaY6YNXjb1TbjWWfYGQ",
|
||||
"dc": 1,
|
||||
"encrypted": {
|
||||
"text": "AQIDBAUGBwgJCg",
|
||||
"cipher": "t4GyXOdaa/phBw"
|
||||
},
|
||||
"decrypted": {
|
||||
"text": "lWNj5kAaug",
|
||||
"cipher": "YWJjZGVmZw"
|
||||
}
|
||||
}
|
||||
+2
-6
@@ -100,12 +100,8 @@ func (p *Proxy) doObfuscated2Handshake(ctx *streamContext) error {
|
||||
return fmt.Errorf("cannot process client handshake: %w", err)
|
||||
}
|
||||
|
||||
if dc < 0 {
|
||||
dc = -dc
|
||||
}
|
||||
|
||||
ctx.dc = int(dc)
|
||||
ctx.logger = ctx.logger.BindInt("dc", ctx.dc)
|
||||
ctx.dc = dc
|
||||
ctx.logger = ctx.logger.BindInt("dc", dc)
|
||||
ctx.clientConn = &obfuscated2.Conn{
|
||||
Conn: ctx.clientConn,
|
||||
Encryptor: encryptor,
|
||||
|
||||
@@ -2,7 +2,7 @@ package stats_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"testing"
|
||||
@@ -32,7 +32,7 @@ func (suite *PrometheusTestSuite) Get() (string, error) {
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", err // nolint: wrapcheck
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user