1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-09-26 13:56:12 -04:00

remove deprecate ciphers in shadowsocks (#566)

* remove deprecate ciphers in shadowsocks
This commit is contained in:
Kslr 2021-01-01 10:18:00 +08:00 committed by GitHub
parent b10108b375
commit 42f0f5dfec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 85 additions and 543 deletions

View File

@ -12,14 +12,6 @@ import (
func cipherFromString(c string) shadowsocks.CipherType { func cipherFromString(c string) shadowsocks.CipherType {
switch strings.ToLower(c) { switch strings.ToLower(c) {
case "aes-256-cfb":
return shadowsocks.CipherType_AES_256_CFB
case "aes-128-cfb":
return shadowsocks.CipherType_AES_128_CFB
case "chacha20":
return shadowsocks.CipherType_CHACHA20
case "chacha20-ietf":
return shadowsocks.CipherType_CHACHA20_IETF
case "aes-128-gcm", "aead_aes_128_gcm": case "aes-128-gcm", "aead_aes_128_gcm":
return shadowsocks.CipherType_AES_128_GCM return shadowsocks.CipherType_AES_128_GCM
case "aes-256-gcm", "aead_aes_256_gcm": case "aes-256-gcm", "aead_aes_256_gcm":

View File

@ -18,14 +18,14 @@ func TestShadowsocksServerConfigParsing(t *testing.T) {
runMultiTestCase(t, []TestCase{ runMultiTestCase(t, []TestCase{
{ {
Input: `{ Input: `{
"method": "aes-128-cfb", "method": "aes-256-GCM",
"password": "v2ray-password" "password": "v2ray-password"
}`, }`,
Parser: loadJSON(creator), Parser: loadJSON(creator),
Output: &shadowsocks.ServerConfig{ Output: &shadowsocks.ServerConfig{
User: &protocol.User{ User: &protocol.User{
Account: serial.ToTypedMessage(&shadowsocks.Account{ Account: serial.ToTypedMessage(&shadowsocks.Account{
CipherType: shadowsocks.CipherType_AES_128_CFB, CipherType: shadowsocks.CipherType_AES_256_GCM,
Password: "v2ray-password", Password: "v2ray-password",
}), }),
}, },

View File

@ -39,22 +39,14 @@ func createAesGcm(key []byte) cipher.AEAD {
return gcm return gcm
} }
func createChacha20Poly1305(key []byte) cipher.AEAD { func createChaCha20Poly1305(key []byte) cipher.AEAD {
chacha20, err := chacha20poly1305.New(key) ChaChaPoly1305, err := chacha20poly1305.New(key)
common.Must(err) common.Must(err)
return chacha20 return ChaChaPoly1305
} }
func (a *Account) getCipher() (Cipher, error) { func (a *Account) getCipher() (Cipher, error) {
switch a.CipherType { switch a.CipherType {
case CipherType_AES_128_CFB:
return &AesCfb{KeyBytes: 16}, nil
case CipherType_AES_256_CFB:
return &AesCfb{KeyBytes: 32}, nil
case CipherType_CHACHA20:
return &ChaCha20{IVBytes: 8}, nil
case CipherType_CHACHA20_IETF:
return &ChaCha20{IVBytes: 12}, nil
case CipherType_AES_128_GCM: case CipherType_AES_128_GCM:
return &AEADCipher{ return &AEADCipher{
KeyBytes: 16, KeyBytes: 16,
@ -71,7 +63,7 @@ func (a *Account) getCipher() (Cipher, error) {
return &AEADCipher{ return &AEADCipher{
KeyBytes: 32, KeyBytes: 32,
IVBytes: 32, IVBytes: 32,
AEADAuthCreator: createChacha20Poly1305, AEADAuthCreator: createChaCha20Poly1305,
}, nil }, nil
case CipherType_NONE: case CipherType_NONE:
return NoneCipher{}, nil return NoneCipher{}, nil
@ -82,13 +74,13 @@ func (a *Account) getCipher() (Cipher, error) {
// AsAccount implements protocol.AsAccount. // AsAccount implements protocol.AsAccount.
func (a *Account) AsAccount() (protocol.Account, error) { func (a *Account) AsAccount() (protocol.Account, error) {
cipher, err := a.getCipher() Cipher, err := a.getCipher()
if err != nil { if err != nil {
return nil, newError("failed to get cipher").Base(err) return nil, newError("failed to get cipher").Base(err)
} }
return &MemoryAccount{ return &MemoryAccount{
Cipher: cipher, Cipher: Cipher,
Key: passwordToCipherKey([]byte(a.Password), cipher.KeySize()), Key: passwordToCipherKey([]byte(a.Password), Cipher.KeySize()),
}, nil }, nil
} }
@ -103,53 +95,6 @@ type Cipher interface {
DecodePacket(key []byte, b *buf.Buffer) error DecodePacket(key []byte, b *buf.Buffer) error
} }
// AesCfb represents all AES-CFB ciphers.
type AesCfb struct {
KeyBytes int32
}
func (*AesCfb) IsAEAD() bool {
return false
}
func (v *AesCfb) KeySize() int32 {
return v.KeyBytes
}
func (v *AesCfb) IVSize() int32 {
return 16
}
func (v *AesCfb) NewEncryptionWriter(key []byte, iv []byte, writer io.Writer) (buf.Writer, error) {
stream := crypto.NewAesEncryptionStream(key, iv)
return &buf.SequentialWriter{Writer: crypto.NewCryptionWriter(stream, writer)}, nil
}
func (v *AesCfb) NewDecryptionReader(key []byte, iv []byte, reader io.Reader) (buf.Reader, error) {
stream := crypto.NewAesDecryptionStream(key, iv)
return &buf.SingleReader{
Reader: crypto.NewCryptionReader(stream, reader),
}, nil
}
func (v *AesCfb) EncodePacket(key []byte, b *buf.Buffer) error {
iv := b.BytesTo(v.IVSize())
stream := crypto.NewAesEncryptionStream(key, iv)
stream.XORKeyStream(b.BytesFrom(v.IVSize()), b.BytesFrom(v.IVSize()))
return nil
}
func (v *AesCfb) DecodePacket(key []byte, b *buf.Buffer) error {
if b.Len() <= v.IVSize() {
return newError("insufficient data: ", b.Len())
}
iv := b.BytesTo(v.IVSize())
stream := crypto.NewAesDecryptionStream(key, iv)
stream.XORKeyStream(b.BytesFrom(v.IVSize()), b.BytesFrom(v.IVSize()))
b.Advance(v.IVSize())
return nil
}
type AEADCipher struct { type AEADCipher struct {
KeyBytes int32 KeyBytes int32
IVBytes int32 IVBytes int32
@ -218,56 +163,12 @@ func (c *AEADCipher) DecodePacket(key []byte, b *buf.Buffer) error {
return nil return nil
} }
type ChaCha20 struct {
IVBytes int32
}
func (*ChaCha20) IsAEAD() bool {
return false
}
func (v *ChaCha20) KeySize() int32 {
return 32
}
func (v *ChaCha20) IVSize() int32 {
return v.IVBytes
}
func (v *ChaCha20) NewEncryptionWriter(key []byte, iv []byte, writer io.Writer) (buf.Writer, error) {
stream := crypto.NewChaCha20Stream(key, iv)
return &buf.SequentialWriter{Writer: crypto.NewCryptionWriter(stream, writer)}, nil
}
func (v *ChaCha20) NewDecryptionReader(key []byte, iv []byte, reader io.Reader) (buf.Reader, error) {
stream := crypto.NewChaCha20Stream(key, iv)
return &buf.SingleReader{Reader: crypto.NewCryptionReader(stream, reader)}, nil
}
func (v *ChaCha20) EncodePacket(key []byte, b *buf.Buffer) error {
iv := b.BytesTo(v.IVSize())
stream := crypto.NewChaCha20Stream(key, iv)
stream.XORKeyStream(b.BytesFrom(v.IVSize()), b.BytesFrom(v.IVSize()))
return nil
}
func (v *ChaCha20) DecodePacket(key []byte, b *buf.Buffer) error {
if b.Len() <= v.IVSize() {
return newError("insufficient data: ", b.Len())
}
iv := b.BytesTo(v.IVSize())
stream := crypto.NewChaCha20Stream(key, iv)
stream.XORKeyStream(b.BytesFrom(v.IVSize()), b.BytesFrom(v.IVSize()))
b.Advance(v.IVSize())
return nil
}
type NoneCipher struct{} type NoneCipher struct{}
func (NoneCipher) KeySize() int32 { return 0 } func (NoneCipher) KeySize() int32 { return 0 }
func (NoneCipher) IVSize() int32 { return 0 } func (NoneCipher) IVSize() int32 { return 0 }
func (NoneCipher) IsAEAD() bool { func (NoneCipher) IsAEAD() bool {
return true // to avoid OTA return false
} }
func (NoneCipher) NewDecryptionReader(key []byte, iv []byte, reader io.Reader) (buf.Reader, error) { func (NoneCipher) NewDecryptionReader(key []byte, iv []byte, reader io.Reader) (buf.Reader, error) {
@ -303,7 +204,7 @@ func passwordToCipherKey(password []byte, keySize int32) []byte {
return key return key
} }
func hkdfSHA1(secret, salt, outkey []byte) { func hkdfSHA1(secret, salt, outKey []byte) {
r := hkdf.New(sha1.New, secret, salt, []byte("ss-subkey")) r := hkdf.New(sha1.New, secret, salt, []byte("ss-subkey"))
common.Must2(io.ReadFull(r, outkey)) common.Must2(io.ReadFull(r, outKey))
} }

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.25.0 // protoc-gen-go v1.25.0
// protoc v3.13.0 // protoc v3.12.4
// source: proxy/shadowsocks/config.proto // source: proxy/shadowsocks/config.proto
package shadowsocks package shadowsocks
@ -31,39 +31,27 @@ type CipherType int32
const ( const (
CipherType_UNKNOWN CipherType = 0 CipherType_UNKNOWN CipherType = 0
CipherType_AES_128_CFB CipherType = 1 CipherType_AES_128_GCM CipherType = 1
CipherType_AES_256_CFB CipherType = 2 CipherType_AES_256_GCM CipherType = 2
CipherType_CHACHA20 CipherType = 3 CipherType_CHACHA20_POLY1305 CipherType = 3
CipherType_CHACHA20_IETF CipherType = 4 CipherType_NONE CipherType = 4
CipherType_AES_128_GCM CipherType = 5
CipherType_AES_256_GCM CipherType = 6
CipherType_CHACHA20_POLY1305 CipherType = 7
CipherType_NONE CipherType = 8
) )
// Enum value maps for CipherType. // Enum value maps for CipherType.
var ( var (
CipherType_name = map[int32]string{ CipherType_name = map[int32]string{
0: "UNKNOWN", 0: "UNKNOWN",
1: "AES_128_CFB", 1: "AES_128_GCM",
2: "AES_256_CFB", 2: "AES_256_GCM",
3: "CHACHA20", 3: "CHACHA20_POLY1305",
4: "CHACHA20_IETF", 4: "NONE",
5: "AES_128_GCM",
6: "AES_256_GCM",
7: "CHACHA20_POLY1305",
8: "NONE",
} }
CipherType_value = map[string]int32{ CipherType_value = map[string]int32{
"UNKNOWN": 0, "UNKNOWN": 0,
"AES_128_CFB": 1, "AES_128_GCM": 1,
"AES_256_CFB": 2, "AES_256_GCM": 2,
"CHACHA20": 3, "CHACHA20_POLY1305": 3,
"CHACHA20_IETF": 4, "NONE": 4,
"AES_128_GCM": 5,
"AES_256_GCM": 6,
"CHACHA20_POLY1305": 7,
"NONE": 8,
} }
) )
@ -299,24 +287,19 @@ var file_proxy_shadowsocks_config_proto_rawDesc = []byte{
0x2a, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2a, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72,
0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65, 0x72,
0x76, 0x65, 0x72, 0x2a, 0x9f, 0x01, 0x0a, 0x0a, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x54, 0x79, 0x76, 0x65, 0x72, 0x2a, 0x5c, 0x0a, 0x0a, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x54, 0x79, 0x70,
0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0f,
0x0f, 0x0a, 0x0b, 0x41, 0x45, 0x53, 0x5f, 0x31, 0x32, 0x38, 0x5f, 0x43, 0x46, 0x42, 0x10, 0x01, 0x0a, 0x0b, 0x41, 0x45, 0x53, 0x5f, 0x31, 0x32, 0x38, 0x5f, 0x47, 0x43, 0x4d, 0x10, 0x01, 0x12,
0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x45, 0x53, 0x5f, 0x32, 0x35, 0x36, 0x5f, 0x43, 0x46, 0x42, 0x10, 0x0f, 0x0a, 0x0b, 0x41, 0x45, 0x53, 0x5f, 0x32, 0x35, 0x36, 0x5f, 0x47, 0x43, 0x4d, 0x10, 0x02,
0x02, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x48, 0x41, 0x43, 0x48, 0x41, 0x32, 0x30, 0x10, 0x03, 0x12, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x48, 0x41, 0x43, 0x48, 0x41, 0x32, 0x30, 0x5f, 0x50, 0x4f, 0x4c,
0x11, 0x0a, 0x0d, 0x43, 0x48, 0x41, 0x43, 0x48, 0x41, 0x32, 0x30, 0x5f, 0x49, 0x45, 0x54, 0x46, 0x59, 0x31, 0x33, 0x30, 0x35, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10,
0x10, 0x04, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x45, 0x53, 0x5f, 0x31, 0x32, 0x38, 0x5f, 0x47, 0x43, 0x04, 0x42, 0x65, 0x0a, 0x20, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63,
0x4d, 0x10, 0x05, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x45, 0x53, 0x5f, 0x32, 0x35, 0x36, 0x5f, 0x47, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77,
0x43, 0x4d, 0x10, 0x06, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x48, 0x41, 0x43, 0x48, 0x41, 0x32, 0x30, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x50, 0x01, 0x5a, 0x20, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63,
0x5f, 0x50, 0x4f, 0x4c, 0x59, 0x31, 0x33, 0x30, 0x35, 0x10, 0x07, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x73, 0x68,
0x4f, 0x4e, 0x45, 0x10, 0x08, 0x42, 0x65, 0x0a, 0x20, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0xaa, 0x02, 0x1c, 0x56, 0x32, 0x52, 0x61,
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x73, 0x68, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x53, 0x68, 0x61,
0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x50, 0x01, 0x5a, 0x20, 0x76, 0x32, 0x72, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78,
0x79, 0x2f, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0xaa, 0x02, 0x1c,
0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79,
0x2e, 0x53, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (

View File

@ -17,14 +17,10 @@ message Account {
enum CipherType { enum CipherType {
UNKNOWN = 0; UNKNOWN = 0;
AES_128_CFB = 1; AES_128_GCM = 1;
AES_256_CFB = 2; AES_256_GCM = 2;
CHACHA20 = 3; CHACHA20_POLY1305 = 3;
CHACHA20_IETF = 4; NONE = 4;
AES_128_GCM = 5;
AES_256_GCM = 6;
CHACHA20_POLY1305 = 7;
NONE = 8;
} }
message ServerConfig { message ServerConfig {

View File

@ -18,6 +18,12 @@ func toAccount(a *Account) protocol.Account {
return account return account
} }
func equalRequestHeader(x, y *protocol.RequestHeader) bool {
return cmp.Equal(x, y, cmp.Comparer(func(x, y protocol.RequestHeader) bool {
return x == y
}))
}
func TestUDPEncoding(t *testing.T) { func TestUDPEncoding(t *testing.T) {
request := &protocol.RequestHeader{ request := &protocol.RequestHeader{
Version: Version, Version: Version,
@ -25,10 +31,10 @@ func TestUDPEncoding(t *testing.T) {
Address: net.LocalHostIP, Address: net.LocalHostIP,
Port: 1234, Port: 1234,
User: &protocol.MemoryUser{ User: &protocol.MemoryUser{
Email: "love@v2ray.com", Email: "love@v2fly.org",
Account: toAccount(&Account{ Account: toAccount(&Account{
Password: "shadowsocks-password", Password: "password",
CipherType: CipherType_AES_128_CFB, CipherType: CipherType_AES_128_GCM,
}), }),
}, },
} }
@ -45,8 +51,8 @@ func TestUDPEncoding(t *testing.T) {
t.Error("data: ", r) t.Error("data: ", r)
} }
if r := cmp.Diff(decodedRequest, request); r != "" { if equalRequestHeader(decodedRequest, request) == false {
t.Error("request: ", r) t.Error("different request")
} }
} }
@ -62,10 +68,10 @@ func TestTCPRequest(t *testing.T) {
Address: net.LocalHostIP, Address: net.LocalHostIP,
Port: 1234, Port: 1234,
User: &protocol.MemoryUser{ User: &protocol.MemoryUser{
Email: "love@v2ray.com", Email: "love@v2fly.org",
Account: toAccount(&Account{ Account: toAccount(&Account{
Password: "tcp-password", Password: "tcp-password",
CipherType: CipherType_CHACHA20, CipherType: CipherType_AES_128_GCM,
}), }),
}, },
}, },
@ -78,10 +84,10 @@ func TestTCPRequest(t *testing.T) {
Address: net.LocalHostIPv6, Address: net.LocalHostIPv6,
Port: 1234, Port: 1234,
User: &protocol.MemoryUser{ User: &protocol.MemoryUser{
Email: "love@v2ray.com", Email: "love@v2fly.org",
Account: toAccount(&Account{ Account: toAccount(&Account{
Password: "password", Password: "password",
CipherType: CipherType_AES_256_CFB, CipherType: CipherType_AES_256_GCM,
}), }),
}, },
}, },
@ -91,13 +97,13 @@ func TestTCPRequest(t *testing.T) {
request: &protocol.RequestHeader{ request: &protocol.RequestHeader{
Version: Version, Version: Version,
Command: protocol.RequestCommandTCP, Command: protocol.RequestCommandTCP,
Address: net.DomainAddress("v2ray.com"), Address: net.DomainAddress("v2fly.org"),
Port: 1234, Port: 1234,
User: &protocol.MemoryUser{ User: &protocol.MemoryUser{
Email: "love@v2ray.com", Email: "love@v2fly.org",
Account: toAccount(&Account{ Account: toAccount(&Account{
Password: "password", Password: "password",
CipherType: CipherType_CHACHA20_IETF, CipherType: CipherType_CHACHA20_POLY1305,
}), }),
}, },
}, },
@ -119,8 +125,8 @@ func TestTCPRequest(t *testing.T) {
decodedRequest, reader, err := ReadTCPSession(request.User, cache) decodedRequest, reader, err := ReadTCPSession(request.User, cache)
common.Must(err) common.Must(err)
if r := cmp.Diff(decodedRequest, request); r != "" { if equalRequestHeader(decodedRequest, request) == false {
t.Error("request: ", r) t.Error("different request")
} }
decodedData, err := reader.ReadMultiBuffer() decodedData, err := reader.ReadMultiBuffer()
@ -139,7 +145,7 @@ func TestUDPReaderWriter(t *testing.T) {
user := &protocol.MemoryUser{ user := &protocol.MemoryUser{
Account: toAccount(&Account{ Account: toAccount(&Account{
Password: "test-password", Password: "test-password",
CipherType: CipherType_CHACHA20_IETF, CipherType: CipherType_CHACHA20_POLY1305,
}), }),
} }
cache := buf.New() cache := buf.New()
@ -149,7 +155,7 @@ func TestUDPReaderWriter(t *testing.T) {
Writer: cache, Writer: cache,
Request: &protocol.RequestHeader{ Request: &protocol.RequestHeader{
Version: Version, Version: Version,
Address: net.DomainAddress("v2ray.com"), Address: net.DomainAddress("v2fly.org"),
Port: 123, Port: 123,
User: user, User: user,
}, },

View File

@ -1,18 +1,15 @@
package scenarios package scenarios
import ( import (
"crypto/rand"
"testing" "testing"
"time" "time"
"github.com/google/go-cmp/cmp"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
"v2ray.com/core" "v2ray.com/core"
"v2ray.com/core/app/log" "v2ray.com/core/app/log"
"v2ray.com/core/app/proxyman" "v2ray.com/core/app/proxyman"
"v2ray.com/core/common" "v2ray.com/core/common"
"v2ray.com/core/common/errors"
clog "v2ray.com/core/common/log" clog "v2ray.com/core/common/log"
"v2ray.com/core/common/net" "v2ray.com/core/common/net"
"v2ray.com/core/common/protocol" "v2ray.com/core/common/protocol"
@ -24,330 +21,7 @@ import (
"v2ray.com/core/testing/servers/udp" "v2ray.com/core/testing/servers/udp"
) )
func TestShadowsocksAES256TCP(t *testing.T) { func TestShadowsocksChaCha20Poly1305TCP(t *testing.T) {
tcpServer := tcp.Server{
MsgProcessor: xor,
}
dest, err := tcpServer.Start()
common.Must(err)
defer tcpServer.Close()
account := serial.ToTypedMessage(&shadowsocks.Account{
Password: "shadowsocks-password",
CipherType: shadowsocks.CipherType_AES_256_CFB,
})
serverPort := tcp.PickPort()
serverConfig := &core.Config{
App: []*serial.TypedMessage{
serial.ToTypedMessage(&log.Config{
ErrorLogLevel: clog.Severity_Debug,
ErrorLogType: log.LogType_Console,
}),
},
Inbound: []*core.InboundHandlerConfig{
{
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
PortRange: net.SinglePortRange(serverPort),
Listen: net.NewIPOrDomain(net.LocalHostIP),
}),
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
User: &protocol.User{
Account: account,
Level: 1,
},
Network: []net.Network{net.Network_TCP},
}),
},
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
},
},
}
clientPort := tcp.PickPort()
clientConfig := &core.Config{
App: []*serial.TypedMessage{
serial.ToTypedMessage(&log.Config{
ErrorLogLevel: clog.Severity_Debug,
ErrorLogType: log.LogType_Console,
}),
},
Inbound: []*core.InboundHandlerConfig{
{
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
PortRange: net.SinglePortRange(clientPort),
Listen: net.NewIPOrDomain(net.LocalHostIP),
}),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port),
NetworkList: &net.NetworkList{
Network: []net.Network{net.Network_TCP},
},
}),
},
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{
Server: []*protocol.ServerEndpoint{
{
Address: net.NewIPOrDomain(net.LocalHostIP),
Port: uint32(serverPort),
User: []*protocol.User{
{
Account: account,
},
},
},
},
}),
},
},
}
servers, err := InitializeServerConfigs(serverConfig, clientConfig)
common.Must(err)
defer CloseAllServers(servers)
var errg errgroup.Group
for i := 0; i < 10; i++ {
errg.Go(testTCPConn(clientPort, 10240*1024, time.Second*20))
}
if err := errg.Wait(); err != nil {
t.Fatal(err)
}
}
func TestShadowsocksAES128UDP(t *testing.T) {
udpServer := udp.Server{
MsgProcessor: xor,
}
dest, err := udpServer.Start()
common.Must(err)
defer udpServer.Close()
account := serial.ToTypedMessage(&shadowsocks.Account{
Password: "shadowsocks-password",
CipherType: shadowsocks.CipherType_AES_128_CFB,
})
serverPort := tcp.PickPort()
serverConfig := &core.Config{
App: []*serial.TypedMessage{
serial.ToTypedMessage(&log.Config{
ErrorLogLevel: clog.Severity_Debug,
ErrorLogType: log.LogType_Console,
}),
},
Inbound: []*core.InboundHandlerConfig{
{
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
PortRange: net.SinglePortRange(serverPort),
Listen: net.NewIPOrDomain(net.LocalHostIP),
}),
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
User: &protocol.User{
Account: account,
Level: 1,
},
Network: []net.Network{net.Network_UDP},
}),
},
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
},
},
}
clientPort := tcp.PickPort()
clientConfig := &core.Config{
App: []*serial.TypedMessage{
serial.ToTypedMessage(&log.Config{
ErrorLogLevel: clog.Severity_Debug,
ErrorLogType: log.LogType_Console,
}),
},
Inbound: []*core.InboundHandlerConfig{
{
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
PortRange: net.SinglePortRange(clientPort),
Listen: net.NewIPOrDomain(net.LocalHostIP),
}),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port),
NetworkList: &net.NetworkList{
Network: []net.Network{net.Network_UDP},
},
}),
},
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{
Server: []*protocol.ServerEndpoint{
{
Address: net.NewIPOrDomain(net.LocalHostIP),
Port: uint32(serverPort),
User: []*protocol.User{
{
Account: account,
},
},
},
},
}),
},
},
}
servers, err := InitializeServerConfigs(serverConfig, clientConfig)
common.Must(err)
defer CloseAllServers(servers)
var errg errgroup.Group
for i := 0; i < 10; i++ {
errg.Go(func() error {
conn, err := net.DialUDP("udp", nil, &net.UDPAddr{
IP: []byte{127, 0, 0, 1},
Port: int(clientPort),
})
if err != nil {
return err
}
defer conn.Close()
payload := make([]byte, 1024)
common.Must2(rand.Read(payload))
nBytes, err := conn.Write(payload)
if err != nil {
return err
}
if nBytes != len(payload) {
return errors.New("expect ", len(payload), " written, but actually ", nBytes)
}
response := readFrom(conn, time.Second*5, 1024)
if r := cmp.Diff(response, xor(payload)); r != "" {
return errors.New(r)
}
return nil
})
}
if err := errg.Wait(); err != nil {
t.Fatal(err)
}
}
func TestShadowsocksChacha20TCP(t *testing.T) {
tcpServer := tcp.Server{
MsgProcessor: xor,
}
dest, err := tcpServer.Start()
common.Must(err)
defer tcpServer.Close()
account := serial.ToTypedMessage(&shadowsocks.Account{
Password: "shadowsocks-password",
CipherType: shadowsocks.CipherType_CHACHA20_IETF,
})
serverPort := tcp.PickPort()
serverConfig := &core.Config{
App: []*serial.TypedMessage{
serial.ToTypedMessage(&log.Config{
ErrorLogLevel: clog.Severity_Debug,
ErrorLogType: log.LogType_Console,
}),
},
Inbound: []*core.InboundHandlerConfig{
{
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
PortRange: net.SinglePortRange(serverPort),
Listen: net.NewIPOrDomain(net.LocalHostIP),
}),
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
User: &protocol.User{
Account: account,
Level: 1,
},
Network: []net.Network{net.Network_TCP},
}),
},
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
},
},
}
clientPort := tcp.PickPort()
clientConfig := &core.Config{
App: []*serial.TypedMessage{
serial.ToTypedMessage(&log.Config{
ErrorLogLevel: clog.Severity_Debug,
ErrorLogType: log.LogType_Console,
}),
},
Inbound: []*core.InboundHandlerConfig{
{
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
PortRange: net.SinglePortRange(clientPort),
Listen: net.NewIPOrDomain(net.LocalHostIP),
}),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port),
NetworkList: &net.NetworkList{
Network: []net.Network{net.Network_TCP},
},
}),
},
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{
Server: []*protocol.ServerEndpoint{
{
Address: net.NewIPOrDomain(net.LocalHostIP),
Port: uint32(serverPort),
User: []*protocol.User{
{
Account: account,
},
},
},
},
}),
},
},
}
servers, err := InitializeServerConfigs(serverConfig, clientConfig)
common.Must(err)
defer CloseAllServers(servers)
var errg errgroup.Group
for i := 0; i < 10; i++ {
errg.Go(testTCPConn(clientPort, 10240*1024, time.Second*40))
}
if err := errg.Wait(); err != nil {
t.Error(err)
}
}
func TestShadowsocksChacha20Poly1305TCP(t *testing.T) {
tcpServer := tcp.Server{ tcpServer := tcp.Server{
MsgProcessor: xor, MsgProcessor: xor,
} }
@ -395,9 +69,7 @@ func TestShadowsocksChacha20Poly1305TCP(t *testing.T) {
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
NetworkList: &net.NetworkList{ Networks: []net.Network{net.Network_TCP},
Network: []net.Network{net.Network_TCP},
},
}), }),
}, },
}, },
@ -424,11 +96,11 @@ func TestShadowsocksChacha20Poly1305TCP(t *testing.T) {
common.Must(err) common.Must(err)
defer CloseAllServers(servers) defer CloseAllServers(servers)
var errg errgroup.Group var errGroup errgroup.Group
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
errg.Go(testTCPConn(clientPort, 10240*1024, time.Second*20)) errGroup.Go(testTCPConn(clientPort, 10240*1024, time.Second*20))
} }
if err := errg.Wait(); err != nil { if err := errGroup.Wait(); err != nil {
t.Error(err) t.Error(err)
} }
} }
@ -493,9 +165,7 @@ func TestShadowsocksAES256GCMTCP(t *testing.T) {
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
NetworkList: &net.NetworkList{ Networks: []net.Network{net.Network_TCP},
Network: []net.Network{net.Network_TCP},
},
}), }),
}, },
}, },
@ -522,12 +192,12 @@ func TestShadowsocksAES256GCMTCP(t *testing.T) {
common.Must(err) common.Must(err)
defer CloseAllServers(servers) defer CloseAllServers(servers)
var errg errgroup.Group var errGroup errgroup.Group
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
errg.Go(testTCPConn(clientPort, 10240*1024, time.Second*20)) errGroup.Go(testTCPConn(clientPort, 10240*1024, time.Second*20))
} }
if err := errg.Wait(); err != nil { if err := errGroup.Wait(); err != nil {
t.Error(err) t.Error(err)
} }
} }
@ -592,9 +262,7 @@ func TestShadowsocksAES128GCMUDP(t *testing.T) {
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
NetworkList: &net.NetworkList{ Networks: []net.Network{net.Network_UDP},
Network: []net.Network{net.Network_UDP},
},
}), }),
}, },
}, },
@ -621,11 +289,11 @@ func TestShadowsocksAES128GCMUDP(t *testing.T) {
common.Must(err) common.Must(err)
defer CloseAllServers(servers) defer CloseAllServers(servers)
var errg errgroup.Group var errGroup errgroup.Group
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
errg.Go(testUDPConn(clientPort, 1024, time.Second*5)) errGroup.Go(testUDPConn(clientPort, 1024, time.Second*5))
} }
if err := errg.Wait(); err != nil { if err := errGroup.Wait(); err != nil {
t.Error(err) t.Error(err)
} }
} }
@ -690,9 +358,7 @@ func TestShadowsocksAES128GCMUDPMux(t *testing.T) {
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
NetworkList: &net.NetworkList{ Networks: []net.Network{net.Network_UDP},
Network: []net.Network{net.Network_UDP},
},
}), }),
}, },
}, },
@ -725,11 +391,11 @@ func TestShadowsocksAES128GCMUDPMux(t *testing.T) {
common.Must(err) common.Must(err)
defer CloseAllServers(servers) defer CloseAllServers(servers)
var errg errgroup.Group var errGroup errgroup.Group
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
errg.Go(testUDPConn(clientPort, 1024, time.Second*5)) errGroup.Go(testUDPConn(clientPort, 1024, time.Second*5))
} }
if err := errg.Wait(); err != nil { if err := errGroup.Wait(); err != nil {
t.Error(err) t.Error(err)
} }
} }
@ -783,9 +449,7 @@ func TestShadowsocksNone(t *testing.T) {
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address), Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port), Port: uint32(dest.Port),
NetworkList: &net.NetworkList{ Networks: []net.Network{net.Network_TCP},
Network: []net.Network{net.Network_TCP},
},
}), }),
}, },
}, },
@ -813,12 +477,12 @@ func TestShadowsocksNone(t *testing.T) {
defer CloseAllServers(servers) defer CloseAllServers(servers)
var errg errgroup.Group var errGroup errgroup.Group
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
errg.Go(testTCPConn(clientPort, 10240*1024, time.Second*20)) errGroup.Go(testTCPConn(clientPort, 10240*1024, time.Second*20))
} }
if err := errg.Wait(); err != nil { if err := errGroup.Wait(); err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }