diff --git a/common/protocol/headers.go b/common/protocol/headers.go index b8fc5885..f3c6e153 100644 --- a/common/protocol/headers.go +++ b/common/protocol/headers.go @@ -38,24 +38,11 @@ const ( RequestOptionChunkMasking bitmask.Byte = 0x04 ) -type Security byte - -func (s Security) Is(t SecurityType) bool { - return s == Security(t) -} - -func NormSecurity(s Security) Security { - if s.Is(SecurityType_UNKNOWN) { - return Security(SecurityType_LEGACY) - } - return s -} - type RequestHeader struct { Version byte Command RequestCommand Option bitmask.Byte - Security Security + Security SecurityType Port net.Port Address net.Address User *User @@ -88,14 +75,14 @@ type CommandSwitchAccount struct { ValidMin byte } -func (sc *SecurityConfig) AsSecurity() Security { +func (sc *SecurityConfig) GetSecurityType() SecurityType { if sc == nil || sc.Type == SecurityType_AUTO { if runtime.GOARCH == "amd64" || runtime.GOARCH == "s390x" { - return Security(SecurityType_AES128_GCM) + return SecurityType_AES128_GCM } - return Security(SecurityType_CHACHA20_POLY1305) + return SecurityType_CHACHA20_POLY1305 } - return NormSecurity(Security(sc.Type)) + return sc.Type } func IsDomainTooLong(domain string) bool { diff --git a/proxy/vmess/account.go b/proxy/vmess/account.go index 57cc1c5a..1efc7eda 100644 --- a/proxy/vmess/account.go +++ b/proxy/vmess/account.go @@ -9,7 +9,7 @@ import ( type InternalAccount struct { ID *protocol.ID AlterIDs []*protocol.ID - Security protocol.Security + Security protocol.SecurityType } func (a *InternalAccount) AnyValidID() *protocol.ID { @@ -37,6 +37,6 @@ func (a *Account) AsAccount() (protocol.Account, error) { return &InternalAccount{ ID: protoID, AlterIDs: protocol.NewAlterIDs(protoID, uint16(a.AlterId)), - Security: a.SecuritySettings.AsSecurity(), + Security: a.SecuritySettings.GetSecurityType(), }, nil } diff --git a/proxy/vmess/encoding/client.go b/proxy/vmess/encoding/client.go index 5b47eb59..6fe18741 100644 --- a/proxy/vmess/encoding/client.go +++ b/proxy/vmess/encoding/client.go @@ -128,7 +128,8 @@ func (c *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, write if request.Option.Has(protocol.RequestOptionChunkMasking) { sizeParser = NewShakeSizeParser(c.requestBodyIV) } - if request.Security.Is(protocol.SecurityType_NONE) { + switch request.Security { + case protocol.SecurityType_NONE: if request.Option.Has(protocol.RequestOptionChunkStream) { if request.Command.TransferType() == protocol.TransferTypeStream { return crypto.NewChunkStreamWriter(sizeParser, writer) @@ -142,9 +143,7 @@ func (c *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, write } return buf.NewWriter(writer) - } - - if request.Security.Is(protocol.SecurityType_LEGACY) { + case protocol.SecurityType_LEGACY: aesStream := crypto.NewAesEncryptionStream(c.requestBodyKey, c.requestBodyIV) cryptionWriter := crypto.NewCryptionWriter(aesStream, writer) if request.Option.Has(protocol.RequestOptionChunkStream) { @@ -157,9 +156,7 @@ func (c *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, write } return buf.NewWriter(cryptionWriter) - } - - if request.Security.Is(protocol.SecurityType_AES128_GCM) { + case protocol.SecurityType_AES128_GCM: block, _ := aes.NewCipher(c.requestBodyKey) aead, _ := cipher.NewGCM(block) @@ -172,9 +169,7 @@ func (c *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, write AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, } return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType()) - } - - if request.Security.Is(protocol.SecurityType_CHACHA20_POLY1305) { + case protocol.SecurityType_CHACHA20_POLY1305: aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(c.requestBodyKey)) auth := &crypto.AEADAuthenticator{ @@ -186,9 +181,9 @@ func (c *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, write AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, } return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType()) + default: + panic("Unknown security type.") } - - panic("Unknown security type.") } func (c *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.ResponseHeader, error) { @@ -231,7 +226,8 @@ func (c *ClientSession) DecodeResponseBody(request *protocol.RequestHeader, read if request.Option.Has(protocol.RequestOptionChunkMasking) { sizeParser = NewShakeSizeParser(c.responseBodyIV) } - if request.Security.Is(protocol.SecurityType_NONE) { + switch request.Security { + case protocol.SecurityType_NONE: if request.Option.Has(protocol.RequestOptionChunkStream) { if request.Command.TransferType() == protocol.TransferTypeStream { return crypto.NewChunkStreamReader(sizeParser, reader) @@ -247,9 +243,7 @@ func (c *ClientSession) DecodeResponseBody(request *protocol.RequestHeader, read } return buf.NewReader(reader) - } - - if request.Security.Is(protocol.SecurityType_LEGACY) { + case protocol.SecurityType_LEGACY: if request.Option.Has(protocol.RequestOptionChunkStream) { auth := &crypto.AEADAuthenticator{ AEAD: new(FnvAuthenticator), @@ -260,9 +254,7 @@ func (c *ClientSession) DecodeResponseBody(request *protocol.RequestHeader, read } return buf.NewReader(c.responseReader) - } - - if request.Security.Is(protocol.SecurityType_AES128_GCM) { + case protocol.SecurityType_AES128_GCM: block, _ := aes.NewCipher(c.responseBodyKey) aead, _ := cipher.NewGCM(block) @@ -275,9 +267,7 @@ func (c *ClientSession) DecodeResponseBody(request *protocol.RequestHeader, read AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, } return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType()) - } - - if request.Security.Is(protocol.SecurityType_CHACHA20_POLY1305) { + case protocol.SecurityType_CHACHA20_POLY1305: aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(c.responseBodyKey)) auth := &crypto.AEADAuthenticator{ @@ -289,9 +279,9 @@ func (c *ClientSession) DecodeResponseBody(request *protocol.RequestHeader, read AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, } return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType()) + default: + panic("Unknown security type.") } - - panic("Unknown security type.") } type ChunkNonceGenerator struct { diff --git a/proxy/vmess/encoding/server.go b/proxy/vmess/encoding/server.go index 2c52287c..10d0e0a3 100644 --- a/proxy/vmess/encoding/server.go +++ b/proxy/vmess/encoding/server.go @@ -143,6 +143,13 @@ func readAddress(buffer *buf.Buffer, reader io.Reader) (net.Address, net.Port, e return address, port, nil } +func parseSecurityType(b byte) protocol.SecurityType { + if _, f := protocol.SecurityType_name[int32(b)]; f { + return protocol.SecurityType(b) + } + return protocol.SecurityType_UNKNOWN +} + func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.RequestHeader, error) { buffer := buf.New() defer buffer.Release() @@ -191,11 +198,24 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request s.responseHeader = buffer.Byte(33) // 1 byte request.Option = bitmask.Byte(buffer.Byte(34)) // 1 byte padingLen := int(buffer.Byte(35) >> 4) - request.Security = protocol.NormSecurity(protocol.Security(buffer.Byte(35) & 0x0F)) + request.Security = parseSecurityType(buffer.Byte(35) & 0x0F) // 1 bytes reserved request.Command = protocol.RequestCommand(buffer.Byte(37)) var invalidRequestErr error + defer func() { + if invalidRequestErr != nil { + randomLen := dice.Roll(64) + 1 + // Read random number of bytes for prevent detection. + buffer.AppendSupplier(buf.ReadFullFrom(decryptor, randomLen)) + } + }() + + if request.Security == protocol.SecurityType_UNKNOWN || request.Security == protocol.SecurityType_AUTO { + invalidRequestErr = newError("unknown security type") + return nil, invalidRequestErr + } + switch request.Command { case protocol.RequestCommandMux: request.Address = net.DomainAddress("v1.mux.cool") @@ -206,15 +226,10 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request request.Port = port } else { invalidRequestErr = newError("invalid address").Base(err) + return nil, invalidRequestErr } default: invalidRequestErr = newError("invalid request command: ", request.Command) - } - - if invalidRequestErr != nil { - randomLen := dice.Roll(32) + 1 - // Read random number of bytes for prevent detection. - buffer.AppendSupplier(buf.ReadFullFrom(decryptor, randomLen)) return nil, invalidRequestErr } @@ -249,7 +264,8 @@ func (s *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade if request.Option.Has(protocol.RequestOptionChunkMasking) { sizeParser = NewShakeSizeParser(s.requestBodyIV) } - if request.Security.Is(protocol.SecurityType_NONE) { + switch request.Security { + case protocol.SecurityType_NONE: if request.Option.Has(protocol.RequestOptionChunkStream) { if request.Command.TransferType() == protocol.TransferTypeStream { return crypto.NewChunkStreamReader(sizeParser, reader) @@ -264,9 +280,7 @@ func (s *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade } return buf.NewReader(reader) - } - - if request.Security.Is(protocol.SecurityType_LEGACY) { + case protocol.SecurityType_LEGACY: aesStream := crypto.NewAesDecryptionStream(s.requestBodyKey, s.requestBodyIV) cryptionReader := crypto.NewCryptionReader(aesStream, reader) if request.Option.Has(protocol.RequestOptionChunkStream) { @@ -279,9 +293,7 @@ func (s *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade } return buf.NewReader(cryptionReader) - } - - if request.Security.Is(protocol.SecurityType_AES128_GCM) { + case protocol.SecurityType_AES128_GCM: block, _ := aes.NewCipher(s.requestBodyKey) aead, _ := cipher.NewGCM(block) @@ -294,9 +306,7 @@ func (s *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, } return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType()) - } - - if request.Security.Is(protocol.SecurityType_CHACHA20_POLY1305) { + case protocol.SecurityType_CHACHA20_POLY1305: aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(s.requestBodyKey)) auth := &crypto.AEADAuthenticator{ @@ -308,9 +318,9 @@ func (s *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, } return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType()) + default: + panic("Unknown security type.") } - - panic("Unknown security type.") } func (s *ServerSession) EncodeResponseHeader(header *protocol.ResponseHeader, writer io.Writer) { @@ -335,7 +345,8 @@ func (s *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writ if request.Option.Has(protocol.RequestOptionChunkMasking) { sizeParser = NewShakeSizeParser(s.responseBodyIV) } - if request.Security.Is(protocol.SecurityType_NONE) { + switch request.Security { + case protocol.SecurityType_NONE: if request.Option.Has(protocol.RequestOptionChunkStream) { if request.Command.TransferType() == protocol.TransferTypeStream { return crypto.NewChunkStreamWriter(sizeParser, writer) @@ -350,9 +361,7 @@ func (s *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writ } return buf.NewWriter(writer) - } - - if request.Security.Is(protocol.SecurityType_LEGACY) { + case protocol.SecurityType_LEGACY: if request.Option.Has(protocol.RequestOptionChunkStream) { auth := &crypto.AEADAuthenticator{ AEAD: new(FnvAuthenticator), @@ -363,9 +372,7 @@ func (s *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writ } return buf.NewWriter(s.responseWriter) - } - - if request.Security.Is(protocol.SecurityType_AES128_GCM) { + case protocol.SecurityType_AES128_GCM: block, _ := aes.NewCipher(s.responseBodyKey) aead, _ := cipher.NewGCM(block) @@ -378,9 +385,7 @@ func (s *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writ AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, } return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType()) - } - - if request.Security.Is(protocol.SecurityType_CHACHA20_POLY1305) { + case protocol.SecurityType_CHACHA20_POLY1305: aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(s.responseBodyKey)) auth := &crypto.AEADAuthenticator{ @@ -392,7 +397,7 @@ func (s *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writ AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, } return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType()) + default: + panic("Unknown security type.") } - - panic("Unknown security type.") } diff --git a/proxy/vmess/inbound/config.pb.go b/proxy/vmess/inbound/config.pb.go index e89c65ed..467653d9 100644 --- a/proxy/vmess/inbound/config.pb.go +++ b/proxy/vmess/inbound/config.pb.go @@ -57,9 +57,10 @@ func (m *DefaultConfig) GetLevel() uint32 { } type Config struct { - User []*v2ray_core_common_protocol.User `protobuf:"bytes,1,rep,name=user" json:"user,omitempty"` - Default *DefaultConfig `protobuf:"bytes,2,opt,name=default" json:"default,omitempty"` - Detour *DetourConfig `protobuf:"bytes,3,opt,name=detour" json:"detour,omitempty"` + User []*v2ray_core_common_protocol.User `protobuf:"bytes,1,rep,name=user" json:"user,omitempty"` + Default *DefaultConfig `protobuf:"bytes,2,opt,name=default" json:"default,omitempty"` + Detour *DetourConfig `protobuf:"bytes,3,opt,name=detour" json:"detour,omitempty"` + SecureEncryptionOnly bool `protobuf:"varint,4,opt,name=secure_encryption_only,json=secureEncryptionOnly" json:"secure_encryption_only,omitempty"` } func (m *Config) Reset() { *m = Config{} } @@ -88,6 +89,13 @@ func (m *Config) GetDetour() *DetourConfig { return nil } +func (m *Config) GetSecureEncryptionOnly() bool { + if m != nil { + return m.SecureEncryptionOnly + } + return false +} + func init() { proto.RegisterType((*DetourConfig)(nil), "v2ray.core.proxy.vmess.inbound.DetourConfig") proto.RegisterType((*DefaultConfig)(nil), "v2ray.core.proxy.vmess.inbound.DefaultConfig") @@ -97,24 +105,26 @@ func init() { func init() { proto.RegisterFile("v2ray.com/core/proxy/vmess/inbound/config.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 297 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x90, 0xcf, 0x4e, 0x83, 0x40, - 0x10, 0xc6, 0x03, 0xd5, 0xa2, 0x5b, 0xeb, 0x81, 0x78, 0x40, 0x0f, 0x84, 0x70, 0xaa, 0x89, 0xce, - 0x26, 0xe8, 0x03, 0x18, 0x4b, 0x62, 0x7a, 0x23, 0x9b, 0xd8, 0x83, 0x17, 0x43, 0x97, 0xad, 0x21, - 0x01, 0xa6, 0x59, 0x16, 0x22, 0xaf, 0xe4, 0xbb, 0xf8, 0x4e, 0xa6, 0x03, 0xc4, 0x3f, 0x07, 0x7b, - 0xdb, 0xd9, 0xfc, 0xbe, 0x6f, 0xbe, 0x6f, 0x18, 0x6f, 0x23, 0x9d, 0x76, 0x20, 0xb1, 0xe4, 0x12, - 0xb5, 0xe2, 0x3b, 0x8d, 0xef, 0x1d, 0x6f, 0x4b, 0x55, 0xd7, 0x3c, 0xaf, 0x36, 0xd8, 0x54, 0x19, - 0x97, 0x58, 0x6d, 0xf3, 0x37, 0xd8, 0x69, 0x34, 0xe8, 0xfa, 0xa3, 0x40, 0x2b, 0x20, 0x18, 0x08, - 0x86, 0x01, 0xbe, 0xba, 0xfe, 0x63, 0x28, 0xb1, 0x2c, 0xb1, 0xe2, 0x24, 0x96, 0x58, 0xf0, 0xa6, - 0x56, 0xba, 0xb7, 0x0a, 0x7d, 0x76, 0x16, 0x2b, 0x83, 0x8d, 0x5e, 0xd2, 0x02, 0xf7, 0x9c, 0xd9, - 0x06, 0x3d, 0x2b, 0xb0, 0x16, 0xa7, 0xc2, 0x36, 0x18, 0x3e, 0xb0, 0x79, 0xac, 0xb6, 0x69, 0x53, - 0x98, 0x01, 0xb8, 0x64, 0x27, 0x69, 0x61, 0x94, 0x7e, 0xcd, 0x33, 0xc2, 0xe6, 0xc2, 0xa1, 0x79, - 0x95, 0xb9, 0x17, 0xec, 0xb8, 0x50, 0xad, 0x2a, 0x3c, 0x9b, 0xfe, 0xfb, 0x21, 0xfc, 0xb4, 0xd8, - 0x74, 0xd0, 0xde, 0xb3, 0xa3, 0xfd, 0x6a, 0xcf, 0x0a, 0x26, 0x8b, 0x59, 0x14, 0xc0, 0x8f, 0x1a, - 0x7d, 0x44, 0x18, 0x23, 0xc2, 0x73, 0xad, 0xb4, 0x20, 0xda, 0x7d, 0x62, 0x4e, 0xd6, 0x47, 0x20, - 0xe3, 0x59, 0x74, 0x0b, 0xff, 0xf7, 0x87, 0x5f, 0x89, 0xc5, 0xa8, 0x76, 0x63, 0x36, 0xcd, 0xa8, - 0xab, 0x37, 0x21, 0x9f, 0x9b, 0xc3, 0x3e, 0xdf, 0x97, 0x11, 0x83, 0xf6, 0x31, 0x61, 0xa1, 0xc4, - 0xf2, 0x80, 0x34, 0xb1, 0x5e, 0x9c, 0xe1, 0xf9, 0x61, 0xfb, 0xeb, 0x48, 0xa4, 0x1d, 0x2c, 0xf7, - 0x6c, 0x42, 0xec, 0x9a, 0xd8, 0x55, 0x0f, 0x6c, 0xa6, 0xd4, 0xfa, 0xee, 0x2b, 0x00, 0x00, 0xff, - 0xff, 0x8d, 0x37, 0x9e, 0x90, 0x08, 0x02, 0x00, 0x00, + // 333 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x90, 0x4f, 0x4f, 0xf2, 0x40, + 0x10, 0xc6, 0xd3, 0xc2, 0x0b, 0xbc, 0x8b, 0x78, 0x68, 0x88, 0xa9, 0x1e, 0x48, 0xd3, 0x13, 0x26, + 0xba, 0x9b, 0x54, 0x3e, 0x80, 0x11, 0x8c, 0xe1, 0x24, 0x69, 0x22, 0x07, 0x2f, 0xa4, 0x6c, 0x07, + 0xd3, 0x64, 0xbb, 0x43, 0xb6, 0x5b, 0x62, 0xcf, 0x7e, 0x1b, 0x3f, 0xa5, 0x61, 0x5a, 0xfc, 0x77, + 0x90, 0xdb, 0xce, 0xce, 0xef, 0x79, 0xe6, 0x99, 0x61, 0x62, 0x17, 0x99, 0xa4, 0xe2, 0x12, 0x73, + 0x21, 0xd1, 0x80, 0xd8, 0x1a, 0x7c, 0xad, 0xc4, 0x2e, 0x87, 0xa2, 0x10, 0x99, 0x5e, 0x63, 0xa9, + 0x53, 0x21, 0x51, 0x6f, 0xb2, 0x17, 0xbe, 0x35, 0x68, 0xd1, 0x1b, 0x1d, 0x04, 0x06, 0x38, 0xc1, + 0x9c, 0x60, 0xde, 0xc0, 0x17, 0x97, 0xbf, 0x0c, 0x25, 0xe6, 0x39, 0x6a, 0x41, 0x62, 0x89, 0x4a, + 0x94, 0x05, 0x98, 0xda, 0x2a, 0x1c, 0xb1, 0x93, 0x19, 0x58, 0x2c, 0xcd, 0x94, 0x06, 0x78, 0xa7, + 0xcc, 0xb5, 0xe8, 0x3b, 0x81, 0x33, 0xfe, 0x1f, 0xbb, 0x16, 0xc3, 0x5b, 0x36, 0x98, 0xc1, 0x26, + 0x29, 0x95, 0x6d, 0x80, 0x73, 0xd6, 0x4b, 0x94, 0x05, 0xb3, 0xca, 0x52, 0xc2, 0x06, 0x71, 0x97, + 0xea, 0x79, 0xea, 0x0d, 0xd9, 0x3f, 0x05, 0x3b, 0x50, 0xbe, 0x4b, 0xff, 0x75, 0x11, 0xbe, 0xb9, + 0xac, 0xd3, 0x68, 0x27, 0xac, 0xbd, 0x1f, 0xed, 0x3b, 0x41, 0x6b, 0xdc, 0x8f, 0x02, 0xfe, 0x6d, + 0x8d, 0x3a, 0x22, 0x3f, 0x44, 0xe4, 0x4f, 0x05, 0x98, 0x98, 0x68, 0xef, 0x81, 0x75, 0xd3, 0x3a, + 0x02, 0x19, 0xf7, 0xa3, 0x6b, 0xfe, 0xf7, 0xfe, 0xfc, 0x47, 0xe2, 0xf8, 0xa0, 0xf6, 0x66, 0xac, + 0x93, 0xd2, 0xae, 0x7e, 0x8b, 0x7c, 0xae, 0x8e, 0xfb, 0x7c, 0x5d, 0x26, 0x6e, 0xb4, 0xde, 0x84, + 0x9d, 0x15, 0x20, 0x4b, 0x03, 0x2b, 0xd0, 0xd2, 0x54, 0x5b, 0x9b, 0xa1, 0x5e, 0xa1, 0x56, 0x95, + 0xdf, 0x0e, 0x9c, 0x71, 0x2f, 0x1e, 0xd6, 0xdd, 0xfb, 0xcf, 0xe6, 0xa3, 0x56, 0xd5, 0xdd, 0x82, + 0x85, 0x12, 0xf3, 0x23, 0x03, 0x17, 0xce, 0x73, 0xb7, 0x79, 0xbe, 0xbb, 0xa3, 0x65, 0x14, 0x27, + 0x15, 0x9f, 0xee, 0xd9, 0x05, 0xb1, 0x4b, 0x62, 0xe7, 0x35, 0xb0, 0xee, 0xd0, 0xad, 0x6e, 0x3e, + 0x02, 0x00, 0x00, 0xff, 0xff, 0xbf, 0x49, 0x84, 0xe1, 0x3e, 0x02, 0x00, 0x00, } diff --git a/proxy/vmess/inbound/config.proto b/proxy/vmess/inbound/config.proto index fa69a203..63caeff8 100644 --- a/proxy/vmess/inbound/config.proto +++ b/proxy/vmess/inbound/config.proto @@ -21,4 +21,5 @@ message Config { repeated v2ray.core.common.protocol.User user = 1; DefaultConfig default = 2; DetourConfig detour = 3; -} \ No newline at end of file + bool secure_encryption_only = 4; +} diff --git a/proxy/vmess/inbound/inbound.go b/proxy/vmess/inbound/inbound.go index 4fb3e45b..df85770e 100644 --- a/proxy/vmess/inbound/inbound.go +++ b/proxy/vmess/inbound/inbound.go @@ -101,6 +101,7 @@ type Handler struct { usersByEmail *userByEmail detours *DetourConfig sessionHistory *encoding.SessionHistory + secure bool } // New creates a new VMess inbound handler. @@ -113,6 +114,7 @@ func New(ctx context.Context, config *Config) (*Handler, error) { detours: config.Detour, usersByEmail: newUserByEmail(config.GetDefaultValue()), sessionHistory: encoding.NewSessionHistory(), + secure: config.SecureEncryptionOnly, } for _, user := range config.User { @@ -210,6 +212,10 @@ func transferResponse(timer signal.ActivityUpdater, session *encoding.ServerSess return nil } +func isInecureEncryption(s protocol.SecurityType) bool { + return s == protocol.SecurityType_NONE || s == protocol.SecurityType_LEGACY || s == protocol.SecurityType_UNKNOWN +} + // Process implements proxy.Inbound.Process(). func (h *Handler) Process(ctx context.Context, network net.Network, connection internet.Connection, dispatcher core.Dispatcher) error { sessionPolicy := h.policyManager.ForLevel(0) @@ -235,6 +241,16 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i return err } + if h.secure && isInecureEncryption(request.Security) { + log.Record(&log.AccessMessage{ + From: connection.RemoteAddr(), + To: "", + Status: log.AccessRejected, + Reason: "Insecure encryption", + }) + return newError("client is using insecure encryption: ", request.Security) + } + log.Record(&log.AccessMessage{ From: connection.RemoteAddr(), To: request.Destination(), diff --git a/proxy/vmess/outbound/outbound.go b/proxy/vmess/outbound/outbound.go index e189f25e..a6b937c1 100644 --- a/proxy/vmess/outbound/outbound.go +++ b/proxy/vmess/outbound/outbound.go @@ -91,7 +91,7 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial account := rawAccount.(*vmess.InternalAccount) request.Security = account.Security - if request.Security.Is(protocol.SecurityType_AES128_GCM) || request.Security.Is(protocol.SecurityType_NONE) || request.Security.Is(protocol.SecurityType_CHACHA20_POLY1305) { + if request.Security == protocol.SecurityType_AES128_GCM || request.Security == protocol.SecurityType_NONE || request.Security == protocol.SecurityType_CHACHA20_POLY1305 { request.Option.Set(protocol.RequestOptionChunkMasking) }