settings for forcing secure encryption in vmess server

pull/876/merge
Darien Raymond 2018-02-23 12:13:02 +01:00
parent 3c1a7ad737
commit 546c2fb226
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
8 changed files with 109 additions and 100 deletions

View File

@ -38,24 +38,11 @@ const (
RequestOptionChunkMasking bitmask.Byte = 0x04 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 { type RequestHeader struct {
Version byte Version byte
Command RequestCommand Command RequestCommand
Option bitmask.Byte Option bitmask.Byte
Security Security Security SecurityType
Port net.Port Port net.Port
Address net.Address Address net.Address
User *User User *User
@ -88,14 +75,14 @@ type CommandSwitchAccount struct {
ValidMin byte ValidMin byte
} }
func (sc *SecurityConfig) AsSecurity() Security { func (sc *SecurityConfig) GetSecurityType() SecurityType {
if sc == nil || sc.Type == SecurityType_AUTO { if sc == nil || sc.Type == SecurityType_AUTO {
if runtime.GOARCH == "amd64" || runtime.GOARCH == "s390x" { 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 { func IsDomainTooLong(domain string) bool {

View File

@ -9,7 +9,7 @@ import (
type InternalAccount struct { type InternalAccount struct {
ID *protocol.ID ID *protocol.ID
AlterIDs []*protocol.ID AlterIDs []*protocol.ID
Security protocol.Security Security protocol.SecurityType
} }
func (a *InternalAccount) AnyValidID() *protocol.ID { func (a *InternalAccount) AnyValidID() *protocol.ID {
@ -37,6 +37,6 @@ func (a *Account) AsAccount() (protocol.Account, error) {
return &InternalAccount{ return &InternalAccount{
ID: protoID, ID: protoID,
AlterIDs: protocol.NewAlterIDs(protoID, uint16(a.AlterId)), AlterIDs: protocol.NewAlterIDs(protoID, uint16(a.AlterId)),
Security: a.SecuritySettings.AsSecurity(), Security: a.SecuritySettings.GetSecurityType(),
}, nil }, nil
} }

View File

@ -128,7 +128,8 @@ func (c *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, write
if request.Option.Has(protocol.RequestOptionChunkMasking) { if request.Option.Has(protocol.RequestOptionChunkMasking) {
sizeParser = NewShakeSizeParser(c.requestBodyIV) 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.Option.Has(protocol.RequestOptionChunkStream) {
if request.Command.TransferType() == protocol.TransferTypeStream { if request.Command.TransferType() == protocol.TransferTypeStream {
return crypto.NewChunkStreamWriter(sizeParser, writer) return crypto.NewChunkStreamWriter(sizeParser, writer)
@ -142,9 +143,7 @@ func (c *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, write
} }
return buf.NewWriter(writer) return buf.NewWriter(writer)
} case protocol.SecurityType_LEGACY:
if request.Security.Is(protocol.SecurityType_LEGACY) {
aesStream := crypto.NewAesEncryptionStream(c.requestBodyKey, c.requestBodyIV) aesStream := crypto.NewAesEncryptionStream(c.requestBodyKey, c.requestBodyIV)
cryptionWriter := crypto.NewCryptionWriter(aesStream, writer) cryptionWriter := crypto.NewCryptionWriter(aesStream, writer)
if request.Option.Has(protocol.RequestOptionChunkStream) { if request.Option.Has(protocol.RequestOptionChunkStream) {
@ -157,9 +156,7 @@ func (c *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, write
} }
return buf.NewWriter(cryptionWriter) return buf.NewWriter(cryptionWriter)
} case protocol.SecurityType_AES128_GCM:
if request.Security.Is(protocol.SecurityType_AES128_GCM) {
block, _ := aes.NewCipher(c.requestBodyKey) block, _ := aes.NewCipher(c.requestBodyKey)
aead, _ := cipher.NewGCM(block) aead, _ := cipher.NewGCM(block)
@ -172,9 +169,7 @@ func (c *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, write
AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
} }
return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType()) return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType())
} case protocol.SecurityType_CHACHA20_POLY1305:
if request.Security.Is(protocol.SecurityType_CHACHA20_POLY1305) {
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(c.requestBodyKey)) aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(c.requestBodyKey))
auth := &crypto.AEADAuthenticator{ auth := &crypto.AEADAuthenticator{
@ -186,9 +181,9 @@ func (c *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, write
AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
} }
return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType()) 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) { 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) { if request.Option.Has(protocol.RequestOptionChunkMasking) {
sizeParser = NewShakeSizeParser(c.responseBodyIV) 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.Option.Has(protocol.RequestOptionChunkStream) {
if request.Command.TransferType() == protocol.TransferTypeStream { if request.Command.TransferType() == protocol.TransferTypeStream {
return crypto.NewChunkStreamReader(sizeParser, reader) return crypto.NewChunkStreamReader(sizeParser, reader)
@ -247,9 +243,7 @@ func (c *ClientSession) DecodeResponseBody(request *protocol.RequestHeader, read
} }
return buf.NewReader(reader) return buf.NewReader(reader)
} case protocol.SecurityType_LEGACY:
if request.Security.Is(protocol.SecurityType_LEGACY) {
if request.Option.Has(protocol.RequestOptionChunkStream) { if request.Option.Has(protocol.RequestOptionChunkStream) {
auth := &crypto.AEADAuthenticator{ auth := &crypto.AEADAuthenticator{
AEAD: new(FnvAuthenticator), AEAD: new(FnvAuthenticator),
@ -260,9 +254,7 @@ func (c *ClientSession) DecodeResponseBody(request *protocol.RequestHeader, read
} }
return buf.NewReader(c.responseReader) return buf.NewReader(c.responseReader)
} case protocol.SecurityType_AES128_GCM:
if request.Security.Is(protocol.SecurityType_AES128_GCM) {
block, _ := aes.NewCipher(c.responseBodyKey) block, _ := aes.NewCipher(c.responseBodyKey)
aead, _ := cipher.NewGCM(block) aead, _ := cipher.NewGCM(block)
@ -275,9 +267,7 @@ func (c *ClientSession) DecodeResponseBody(request *protocol.RequestHeader, read
AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
} }
return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType()) return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType())
} case protocol.SecurityType_CHACHA20_POLY1305:
if request.Security.Is(protocol.SecurityType_CHACHA20_POLY1305) {
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(c.responseBodyKey)) aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(c.responseBodyKey))
auth := &crypto.AEADAuthenticator{ auth := &crypto.AEADAuthenticator{
@ -289,9 +279,9 @@ func (c *ClientSession) DecodeResponseBody(request *protocol.RequestHeader, read
AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
} }
return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType()) return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType())
default:
panic("Unknown security type.")
} }
panic("Unknown security type.")
} }
type ChunkNonceGenerator struct { type ChunkNonceGenerator struct {

View File

@ -143,6 +143,13 @@ func readAddress(buffer *buf.Buffer, reader io.Reader) (net.Address, net.Port, e
return address, port, nil 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) { func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.RequestHeader, error) {
buffer := buf.New() buffer := buf.New()
defer buffer.Release() defer buffer.Release()
@ -191,11 +198,24 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
s.responseHeader = buffer.Byte(33) // 1 byte s.responseHeader = buffer.Byte(33) // 1 byte
request.Option = bitmask.Byte(buffer.Byte(34)) // 1 byte request.Option = bitmask.Byte(buffer.Byte(34)) // 1 byte
padingLen := int(buffer.Byte(35) >> 4) 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 // 1 bytes reserved
request.Command = protocol.RequestCommand(buffer.Byte(37)) request.Command = protocol.RequestCommand(buffer.Byte(37))
var invalidRequestErr error 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 { switch request.Command {
case protocol.RequestCommandMux: case protocol.RequestCommandMux:
request.Address = net.DomainAddress("v1.mux.cool") request.Address = net.DomainAddress("v1.mux.cool")
@ -206,15 +226,10 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
request.Port = port request.Port = port
} else { } else {
invalidRequestErr = newError("invalid address").Base(err) invalidRequestErr = newError("invalid address").Base(err)
return nil, invalidRequestErr
} }
default: default:
invalidRequestErr = newError("invalid request command: ", request.Command) 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 return nil, invalidRequestErr
} }
@ -249,7 +264,8 @@ func (s *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade
if request.Option.Has(protocol.RequestOptionChunkMasking) { if request.Option.Has(protocol.RequestOptionChunkMasking) {
sizeParser = NewShakeSizeParser(s.requestBodyIV) 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.Option.Has(protocol.RequestOptionChunkStream) {
if request.Command.TransferType() == protocol.TransferTypeStream { if request.Command.TransferType() == protocol.TransferTypeStream {
return crypto.NewChunkStreamReader(sizeParser, reader) return crypto.NewChunkStreamReader(sizeParser, reader)
@ -264,9 +280,7 @@ func (s *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade
} }
return buf.NewReader(reader) return buf.NewReader(reader)
} case protocol.SecurityType_LEGACY:
if request.Security.Is(protocol.SecurityType_LEGACY) {
aesStream := crypto.NewAesDecryptionStream(s.requestBodyKey, s.requestBodyIV) aesStream := crypto.NewAesDecryptionStream(s.requestBodyKey, s.requestBodyIV)
cryptionReader := crypto.NewCryptionReader(aesStream, reader) cryptionReader := crypto.NewCryptionReader(aesStream, reader)
if request.Option.Has(protocol.RequestOptionChunkStream) { if request.Option.Has(protocol.RequestOptionChunkStream) {
@ -279,9 +293,7 @@ func (s *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade
} }
return buf.NewReader(cryptionReader) return buf.NewReader(cryptionReader)
} case protocol.SecurityType_AES128_GCM:
if request.Security.Is(protocol.SecurityType_AES128_GCM) {
block, _ := aes.NewCipher(s.requestBodyKey) block, _ := aes.NewCipher(s.requestBodyKey)
aead, _ := cipher.NewGCM(block) aead, _ := cipher.NewGCM(block)
@ -294,9 +306,7 @@ func (s *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade
AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
} }
return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType()) return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType())
} case protocol.SecurityType_CHACHA20_POLY1305:
if request.Security.Is(protocol.SecurityType_CHACHA20_POLY1305) {
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(s.requestBodyKey)) aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(s.requestBodyKey))
auth := &crypto.AEADAuthenticator{ auth := &crypto.AEADAuthenticator{
@ -308,9 +318,9 @@ func (s *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade
AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
} }
return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType()) 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) { 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) { if request.Option.Has(protocol.RequestOptionChunkMasking) {
sizeParser = NewShakeSizeParser(s.responseBodyIV) 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.Option.Has(protocol.RequestOptionChunkStream) {
if request.Command.TransferType() == protocol.TransferTypeStream { if request.Command.TransferType() == protocol.TransferTypeStream {
return crypto.NewChunkStreamWriter(sizeParser, writer) return crypto.NewChunkStreamWriter(sizeParser, writer)
@ -350,9 +361,7 @@ func (s *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writ
} }
return buf.NewWriter(writer) return buf.NewWriter(writer)
} case protocol.SecurityType_LEGACY:
if request.Security.Is(protocol.SecurityType_LEGACY) {
if request.Option.Has(protocol.RequestOptionChunkStream) { if request.Option.Has(protocol.RequestOptionChunkStream) {
auth := &crypto.AEADAuthenticator{ auth := &crypto.AEADAuthenticator{
AEAD: new(FnvAuthenticator), AEAD: new(FnvAuthenticator),
@ -363,9 +372,7 @@ func (s *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writ
} }
return buf.NewWriter(s.responseWriter) return buf.NewWriter(s.responseWriter)
} case protocol.SecurityType_AES128_GCM:
if request.Security.Is(protocol.SecurityType_AES128_GCM) {
block, _ := aes.NewCipher(s.responseBodyKey) block, _ := aes.NewCipher(s.responseBodyKey)
aead, _ := cipher.NewGCM(block) aead, _ := cipher.NewGCM(block)
@ -378,9 +385,7 @@ func (s *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writ
AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
} }
return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType()) return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType())
} case protocol.SecurityType_CHACHA20_POLY1305:
if request.Security.Is(protocol.SecurityType_CHACHA20_POLY1305) {
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(s.responseBodyKey)) aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(s.responseBodyKey))
auth := &crypto.AEADAuthenticator{ auth := &crypto.AEADAuthenticator{
@ -392,7 +397,7 @@ func (s *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writ
AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
} }
return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType()) return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType())
default:
panic("Unknown security type.")
} }
panic("Unknown security type.")
} }

View File

@ -57,9 +57,10 @@ func (m *DefaultConfig) GetLevel() uint32 {
} }
type Config struct { type Config struct {
User []*v2ray_core_common_protocol.User `protobuf:"bytes,1,rep,name=user" json:"user,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"` Default *DefaultConfig `protobuf:"bytes,2,opt,name=default" json:"default,omitempty"`
Detour *DetourConfig `protobuf:"bytes,3,opt,name=detour" json:"detour,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{} } func (m *Config) Reset() { *m = Config{} }
@ -88,6 +89,13 @@ func (m *Config) GetDetour() *DetourConfig {
return nil return nil
} }
func (m *Config) GetSecureEncryptionOnly() bool {
if m != nil {
return m.SecureEncryptionOnly
}
return false
}
func init() { func init() {
proto.RegisterType((*DetourConfig)(nil), "v2ray.core.proxy.vmess.inbound.DetourConfig") proto.RegisterType((*DetourConfig)(nil), "v2ray.core.proxy.vmess.inbound.DetourConfig")
proto.RegisterType((*DefaultConfig)(nil), "v2ray.core.proxy.vmess.inbound.DefaultConfig") 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) } func init() { proto.RegisterFile("v2ray.com/core/proxy/vmess/inbound/config.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{ var fileDescriptor0 = []byte{
// 297 bytes of a gzipped FileDescriptorProto // 333 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x90, 0xcf, 0x4e, 0x83, 0x40, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x90, 0x4f, 0x4f, 0xf2, 0x40,
0x10, 0xc6, 0x03, 0xd5, 0xa2, 0x5b, 0xeb, 0x81, 0x78, 0x40, 0x0f, 0x84, 0x70, 0xaa, 0x89, 0xce, 0x10, 0xc6, 0xd3, 0xc2, 0x0b, 0xbc, 0x8b, 0x78, 0x68, 0x88, 0xa9, 0x1e, 0x48, 0xd3, 0x13, 0x26,
0x26, 0xe8, 0x03, 0x18, 0x4b, 0x62, 0x7a, 0x23, 0x9b, 0xd8, 0x83, 0x17, 0x43, 0x97, 0xad, 0x21, 0xba, 0x9b, 0x54, 0x3e, 0x80, 0x11, 0x8c, 0xe1, 0x24, 0x69, 0x22, 0x07, 0x2f, 0xa4, 0x6c, 0x07,
0x01, 0xa6, 0x59, 0x16, 0x22, 0xaf, 0xe4, 0xbb, 0xf8, 0x4e, 0xa6, 0x03, 0xc4, 0x3f, 0x07, 0x7b, 0xd3, 0x64, 0xbb, 0x43, 0xb6, 0x5b, 0x62, 0xcf, 0x7e, 0x1b, 0x3f, 0xa5, 0x61, 0x5a, 0xfc, 0x77,
0xdb, 0xd9, 0xfc, 0xbe, 0x6f, 0xbe, 0x6f, 0x18, 0x6f, 0x23, 0x9d, 0x76, 0x20, 0xb1, 0xe4, 0x12, 0x90, 0xdb, 0xce, 0xce, 0xef, 0x79, 0xe6, 0x99, 0x61, 0x62, 0x17, 0x99, 0xa4, 0xe2, 0x12, 0x73,
0xb5, 0xe2, 0x3b, 0x8d, 0xef, 0x1d, 0x6f, 0x4b, 0x55, 0xd7, 0x3c, 0xaf, 0x36, 0xd8, 0x54, 0x19, 0x21, 0xd1, 0x80, 0xd8, 0x1a, 0x7c, 0xad, 0xc4, 0x2e, 0x87, 0xa2, 0x10, 0x99, 0x5e, 0x63, 0xa9,
0x97, 0x58, 0x6d, 0xf3, 0x37, 0xd8, 0x69, 0x34, 0xe8, 0xfa, 0xa3, 0x40, 0x2b, 0x20, 0x18, 0x08, 0x53, 0x21, 0x51, 0x6f, 0xb2, 0x17, 0xbe, 0x35, 0x68, 0xd1, 0x1b, 0x1d, 0x04, 0x06, 0x38, 0xc1,
0x86, 0x01, 0xbe, 0xba, 0xfe, 0x63, 0x28, 0xb1, 0x2c, 0xb1, 0xe2, 0x24, 0x96, 0x58, 0xf0, 0xa6, 0x9c, 0x60, 0xde, 0xc0, 0x17, 0x97, 0xbf, 0x0c, 0x25, 0xe6, 0x39, 0x6a, 0x41, 0x62, 0x89, 0x4a,
0x56, 0xba, 0xb7, 0x0a, 0x7d, 0x76, 0x16, 0x2b, 0x83, 0x8d, 0x5e, 0xd2, 0x02, 0xf7, 0x9c, 0xd9, 0x94, 0x05, 0x98, 0xda, 0x2a, 0x1c, 0xb1, 0x93, 0x19, 0x58, 0x2c, 0xcd, 0x94, 0x06, 0x78, 0xa7,
0x06, 0x3d, 0x2b, 0xb0, 0x16, 0xa7, 0xc2, 0x36, 0x18, 0x3e, 0xb0, 0x79, 0xac, 0xb6, 0x69, 0x53, 0xcc, 0xb5, 0xe8, 0x3b, 0x81, 0x33, 0xfe, 0x1f, 0xbb, 0x16, 0xc3, 0x5b, 0x36, 0x98, 0xc1, 0x26,
0x98, 0x01, 0xb8, 0x64, 0x27, 0x69, 0x61, 0x94, 0x7e, 0xcd, 0x33, 0xc2, 0xe6, 0xc2, 0xa1, 0x79, 0x29, 0x95, 0x6d, 0x80, 0x73, 0xd6, 0x4b, 0x94, 0x05, 0xb3, 0xca, 0x52, 0xc2, 0x06, 0x71, 0x97,
0x95, 0xb9, 0x17, 0xec, 0xb8, 0x50, 0xad, 0x2a, 0x3c, 0x9b, 0xfe, 0xfb, 0x21, 0xfc, 0xb4, 0xd8, 0xea, 0x79, 0xea, 0x0d, 0xd9, 0x3f, 0x05, 0x3b, 0x50, 0xbe, 0x4b, 0xff, 0x75, 0x11, 0xbe, 0xb9,
0x74, 0xd0, 0xde, 0xb3, 0xa3, 0xfd, 0x6a, 0xcf, 0x0a, 0x26, 0x8b, 0x59, 0x14, 0xc0, 0x8f, 0x1a, 0xac, 0xd3, 0x68, 0x27, 0xac, 0xbd, 0x1f, 0xed, 0x3b, 0x41, 0x6b, 0xdc, 0x8f, 0x02, 0xfe, 0x6d,
0x7d, 0x44, 0x18, 0x23, 0xc2, 0x73, 0xad, 0xb4, 0x20, 0xda, 0x7d, 0x62, 0x4e, 0xd6, 0x47, 0x20, 0x8d, 0x3a, 0x22, 0x3f, 0x44, 0xe4, 0x4f, 0x05, 0x98, 0x98, 0x68, 0xef, 0x81, 0x75, 0xd3, 0x3a,
0xe3, 0x59, 0x74, 0x0b, 0xff, 0xf7, 0x87, 0x5f, 0x89, 0xc5, 0xa8, 0x76, 0x63, 0x36, 0xcd, 0xa8, 0x02, 0x19, 0xf7, 0xa3, 0x6b, 0xfe, 0xf7, 0xfe, 0xfc, 0x47, 0xe2, 0xf8, 0xa0, 0xf6, 0x66, 0xac,
0xab, 0x37, 0x21, 0x9f, 0x9b, 0xc3, 0x3e, 0xdf, 0x97, 0x11, 0x83, 0xf6, 0x31, 0x61, 0xa1, 0xc4, 0x93, 0xd2, 0xae, 0x7e, 0x8b, 0x7c, 0xae, 0x8e, 0xfb, 0x7c, 0x5d, 0x26, 0x6e, 0xb4, 0xde, 0x84,
0xf2, 0x80, 0x34, 0xb1, 0x5e, 0x9c, 0xe1, 0xf9, 0x61, 0xfb, 0xeb, 0x48, 0xa4, 0x1d, 0x2c, 0xf7, 0x9d, 0x15, 0x20, 0x4b, 0x03, 0x2b, 0xd0, 0xd2, 0x54, 0x5b, 0x9b, 0xa1, 0x5e, 0xa1, 0x56, 0x95,
0x6c, 0x42, 0xec, 0x9a, 0xd8, 0x55, 0x0f, 0x6c, 0xa6, 0xd4, 0xfa, 0xee, 0x2b, 0x00, 0x00, 0xff, 0xdf, 0x0e, 0x9c, 0x71, 0x2f, 0x1e, 0xd6, 0xdd, 0xfb, 0xcf, 0xe6, 0xa3, 0x56, 0xd5, 0xdd, 0x82,
0xff, 0x8d, 0x37, 0x9e, 0x90, 0x08, 0x02, 0x00, 0x00, 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,
} }

View File

@ -21,4 +21,5 @@ message Config {
repeated v2ray.core.common.protocol.User user = 1; repeated v2ray.core.common.protocol.User user = 1;
DefaultConfig default = 2; DefaultConfig default = 2;
DetourConfig detour = 3; DetourConfig detour = 3;
} bool secure_encryption_only = 4;
}

View File

@ -101,6 +101,7 @@ type Handler struct {
usersByEmail *userByEmail usersByEmail *userByEmail
detours *DetourConfig detours *DetourConfig
sessionHistory *encoding.SessionHistory sessionHistory *encoding.SessionHistory
secure bool
} }
// New creates a new VMess inbound handler. // New creates a new VMess inbound handler.
@ -113,6 +114,7 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
detours: config.Detour, detours: config.Detour,
usersByEmail: newUserByEmail(config.GetDefaultValue()), usersByEmail: newUserByEmail(config.GetDefaultValue()),
sessionHistory: encoding.NewSessionHistory(), sessionHistory: encoding.NewSessionHistory(),
secure: config.SecureEncryptionOnly,
} }
for _, user := range config.User { for _, user := range config.User {
@ -210,6 +212,10 @@ func transferResponse(timer signal.ActivityUpdater, session *encoding.ServerSess
return nil 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(). // Process implements proxy.Inbound.Process().
func (h *Handler) Process(ctx context.Context, network net.Network, connection internet.Connection, dispatcher core.Dispatcher) error { func (h *Handler) Process(ctx context.Context, network net.Network, connection internet.Connection, dispatcher core.Dispatcher) error {
sessionPolicy := h.policyManager.ForLevel(0) sessionPolicy := h.policyManager.ForLevel(0)
@ -235,6 +241,16 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i
return err 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{ log.Record(&log.AccessMessage{
From: connection.RemoteAddr(), From: connection.RemoteAddr(),
To: request.Destination(), To: request.Destination(),

View File

@ -91,7 +91,7 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial
account := rawAccount.(*vmess.InternalAccount) account := rawAccount.(*vmess.InternalAccount)
request.Security = account.Security 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) request.Option.Set(protocol.RequestOptionChunkMasking)
} }