reduce memory usage of vmess internal objects

pull/1059/head
Darien Raymond 2018-04-14 15:05:49 +02:00
parent da0568d8d0
commit 0caf2a004b
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
5 changed files with 53 additions and 62 deletions

View File

@ -1,7 +0,0 @@
package protocol
type UserValidator interface {
Add(user *User) error
Get(timeHash []byte) (*User, Timestamp, bool)
Remove(email string) bool
}

View File

@ -31,13 +31,13 @@ func hashTimestamp(t protocol.Timestamp) []byte {
// ClientSession stores connection session info for VMess client.
type ClientSession struct {
requestBodyKey []byte
requestBodyIV []byte
responseHeader byte
responseBodyKey []byte
responseBodyIV []byte
responseReader io.Reader
idHash protocol.IDHash
requestBodyKey [16]byte
requestBodyIV [16]byte
responseBodyKey [16]byte
responseBodyIV [16]byte
responseReader io.Reader
responseHeader byte
}
// NewClientSession creates a new ClientSession.
@ -46,13 +46,11 @@ func NewClientSession(idHash protocol.IDHash) *ClientSession {
common.Must2(rand.Read(randomBytes))
session := &ClientSession{}
session.requestBodyKey = randomBytes[:16]
session.requestBodyIV = randomBytes[16:32]
copy(session.requestBodyKey[:], randomBytes[:16])
copy(session.requestBodyIV[:], randomBytes[16:32])
session.responseHeader = randomBytes[32]
responseBodyKey := md5.Sum(session.requestBodyKey)
responseBodyIV := md5.Sum(session.requestBodyIV)
session.responseBodyKey = responseBodyKey[:]
session.responseBodyIV = responseBodyIV[:]
session.responseBodyKey = md5.Sum(session.requestBodyKey[:])
session.responseBodyIV = md5.Sum(session.requestBodyIV[:])
session.idHash = idHash
return session
@ -72,8 +70,8 @@ func (c *ClientSession) EncodeRequestHeader(header *protocol.RequestHeader, writ
defer buffer.Release()
buffer.AppendBytes(Version)
buffer.Append(c.requestBodyIV)
buffer.Append(c.requestBodyKey)
buffer.Append(c.requestBodyIV[:])
buffer.Append(c.requestBodyKey[:])
buffer.AppendBytes(c.responseHeader, byte(header.Option))
padingLen := dice.Roll(16)
@ -110,7 +108,7 @@ func (c *ClientSession) EncodeRequestHeader(header *protocol.RequestHeader, writ
func (c *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, writer io.Writer) buf.Writer {
var sizeParser crypto.ChunkSizeEncoder = crypto.PlainChunkSizeParser{}
if request.Option.Has(protocol.RequestOptionChunkMasking) {
sizeParser = NewShakeSizeParser(c.requestBodyIV)
sizeParser = NewShakeSizeParser(c.requestBodyIV[:])
}
switch request.Security {
case protocol.SecurityType_NONE:
@ -128,7 +126,7 @@ func (c *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, write
return buf.NewWriter(writer)
case protocol.SecurityType_LEGACY:
aesStream := crypto.NewAesEncryptionStream(c.requestBodyKey, c.requestBodyIV)
aesStream := crypto.NewAesEncryptionStream(c.requestBodyKey[:], c.requestBodyIV[:])
cryptionWriter := crypto.NewCryptionWriter(aesStream, writer)
if request.Option.Has(protocol.RequestOptionChunkStream) {
auth := &crypto.AEADAuthenticator{
@ -141,21 +139,21 @@ func (c *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, write
return buf.NewWriter(cryptionWriter)
case protocol.SecurityType_AES128_GCM:
block, _ := aes.NewCipher(c.requestBodyKey)
block, _ := aes.NewCipher(c.requestBodyKey[:])
aead, _ := cipher.NewGCM(block)
auth := &crypto.AEADAuthenticator{
AEAD: aead,
NonceGenerator: GenerateChunkNonce(c.requestBodyIV, uint32(aead.NonceSize())),
NonceGenerator: GenerateChunkNonce(c.requestBodyIV[:], uint32(aead.NonceSize())),
AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
}
return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType())
case protocol.SecurityType_CHACHA20_POLY1305:
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(c.requestBodyKey))
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(c.requestBodyKey[:]))
auth := &crypto.AEADAuthenticator{
AEAD: aead,
NonceGenerator: GenerateChunkNonce(c.requestBodyIV, uint32(aead.NonceSize())),
NonceGenerator: GenerateChunkNonce(c.requestBodyIV[:], uint32(aead.NonceSize())),
AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
}
return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType())
@ -165,7 +163,7 @@ func (c *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, write
}
func (c *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.ResponseHeader, error) {
aesStream := crypto.NewAesDecryptionStream(c.responseBodyKey, c.responseBodyIV)
aesStream := crypto.NewAesDecryptionStream(c.responseBodyKey[:], c.responseBodyIV[:])
c.responseReader = crypto.NewCryptionReader(aesStream, reader)
buffer := buf.New()
@ -202,7 +200,7 @@ func (c *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.Respon
func (c *ClientSession) DecodeResponseBody(request *protocol.RequestHeader, reader io.Reader) buf.Reader {
var sizeParser crypto.ChunkSizeDecoder = crypto.PlainChunkSizeParser{}
if request.Option.Has(protocol.RequestOptionChunkMasking) {
sizeParser = NewShakeSizeParser(c.responseBodyIV)
sizeParser = NewShakeSizeParser(c.responseBodyIV[:])
}
switch request.Security {
case protocol.SecurityType_NONE:
@ -233,21 +231,21 @@ func (c *ClientSession) DecodeResponseBody(request *protocol.RequestHeader, read
return buf.NewReader(c.responseReader)
case protocol.SecurityType_AES128_GCM:
block, _ := aes.NewCipher(c.responseBodyKey)
block, _ := aes.NewCipher(c.responseBodyKey[:])
aead, _ := cipher.NewGCM(block)
auth := &crypto.AEADAuthenticator{
AEAD: aead,
NonceGenerator: GenerateChunkNonce(c.responseBodyIV, uint32(aead.NonceSize())),
NonceGenerator: GenerateChunkNonce(c.responseBodyIV[:], uint32(aead.NonceSize())),
AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
}
return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType())
case protocol.SecurityType_CHACHA20_POLY1305:
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(c.responseBodyKey))
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(c.responseBodyKey[:]))
auth := &crypto.AEADAuthenticator{
AEAD: aead,
NonceGenerator: GenerateChunkNonce(c.responseBodyIV, uint32(aead.NonceSize())),
NonceGenerator: GenerateChunkNonce(c.responseBodyIV[:], uint32(aead.NonceSize())),
AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
}
return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType())

View File

@ -85,19 +85,19 @@ func (h *SessionHistory) removeExpiredEntries() {
}
type ServerSession struct {
userValidator protocol.UserValidator
userValidator *vmess.TimedUserValidator
sessionHistory *SessionHistory
requestBodyKey []byte
requestBodyIV []byte
responseBodyKey []byte
responseBodyIV []byte
responseHeader byte
requestBodyKey [16]byte
requestBodyIV [16]byte
responseBodyKey [16]byte
responseBodyIV [16]byte
responseWriter io.Writer
responseHeader byte
}
// NewServerSession creates a new ServerSession, using the given UserValidator.
// The ServerSession instance doesn't take ownership of the validator.
func NewServerSession(validator protocol.UserValidator, sessionHistory *SessionHistory) *ServerSession {
func NewServerSession(validator *vmess.TimedUserValidator, sessionHistory *SessionHistory) *ServerSession {
return &ServerSession{
userValidator: validator,
sessionHistory: sessionHistory,
@ -150,12 +150,12 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
Version: buffer.Byte(0),
}
s.requestBodyIV = append([]byte(nil), buffer.BytesRange(1, 17)...) // 16 bytes
s.requestBodyKey = append([]byte(nil), buffer.BytesRange(17, 33)...) // 16 bytes
copy(s.requestBodyIV[:], buffer.BytesRange(1, 17)) // 16 bytes
copy(s.requestBodyKey[:], buffer.BytesRange(17, 33)) // 16 bytes
var sid sessionId
copy(sid.user[:], vmessAccount.ID.Bytes())
copy(sid.key[:], s.requestBodyKey)
copy(sid.nonce[:], s.requestBodyIV)
sid.key = s.requestBodyKey
sid.nonce = s.requestBodyIV
if !s.sessionHistory.addIfNotExits(sid) {
return nil, newError("duplicated session id, possibly under replay attack")
}
@ -227,7 +227,7 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
func (s *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reader io.Reader) buf.Reader {
var sizeParser crypto.ChunkSizeDecoder = crypto.PlainChunkSizeParser{}
if request.Option.Has(protocol.RequestOptionChunkMasking) {
sizeParser = NewShakeSizeParser(s.requestBodyIV)
sizeParser = NewShakeSizeParser(s.requestBodyIV[:])
}
switch request.Security {
case protocol.SecurityType_NONE:
@ -246,7 +246,7 @@ func (s *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade
return buf.NewReader(reader)
case protocol.SecurityType_LEGACY:
aesStream := crypto.NewAesDecryptionStream(s.requestBodyKey, s.requestBodyIV)
aesStream := crypto.NewAesDecryptionStream(s.requestBodyKey[:], s.requestBodyIV[:])
cryptionReader := crypto.NewCryptionReader(aesStream, reader)
if request.Option.Has(protocol.RequestOptionChunkStream) {
auth := &crypto.AEADAuthenticator{
@ -259,21 +259,21 @@ func (s *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade
return buf.NewReader(cryptionReader)
case protocol.SecurityType_AES128_GCM:
block, _ := aes.NewCipher(s.requestBodyKey)
block, _ := aes.NewCipher(s.requestBodyKey[:])
aead, _ := cipher.NewGCM(block)
auth := &crypto.AEADAuthenticator{
AEAD: aead,
NonceGenerator: GenerateChunkNonce(s.requestBodyIV, uint32(aead.NonceSize())),
NonceGenerator: GenerateChunkNonce(s.requestBodyIV[:], uint32(aead.NonceSize())),
AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
}
return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType())
case protocol.SecurityType_CHACHA20_POLY1305:
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(s.requestBodyKey))
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(s.requestBodyKey[:]))
auth := &crypto.AEADAuthenticator{
AEAD: aead,
NonceGenerator: GenerateChunkNonce(s.requestBodyIV, uint32(aead.NonceSize())),
NonceGenerator: GenerateChunkNonce(s.requestBodyIV[:], uint32(aead.NonceSize())),
AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
}
return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType())
@ -283,12 +283,12 @@ func (s *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade
}
func (s *ServerSession) EncodeResponseHeader(header *protocol.ResponseHeader, writer io.Writer) {
responseBodyKey := md5.Sum(s.requestBodyKey)
responseBodyIV := md5.Sum(s.requestBodyIV)
s.responseBodyKey = responseBodyKey[:]
s.responseBodyIV = responseBodyIV[:]
responseBodyKey := md5.Sum(s.requestBodyKey[:])
responseBodyIV := md5.Sum(s.requestBodyIV[:])
s.responseBodyKey = responseBodyKey
s.responseBodyIV = responseBodyIV
aesStream := crypto.NewAesEncryptionStream(s.responseBodyKey, s.responseBodyIV)
aesStream := crypto.NewAesEncryptionStream(s.responseBodyKey[:], s.responseBodyIV[:])
encryptionWriter := crypto.NewCryptionWriter(aesStream, writer)
s.responseWriter = encryptionWriter
@ -302,7 +302,7 @@ func (s *ServerSession) EncodeResponseHeader(header *protocol.ResponseHeader, wr
func (s *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writer io.Writer) buf.Writer {
var sizeParser crypto.ChunkSizeEncoder = crypto.PlainChunkSizeParser{}
if request.Option.Has(protocol.RequestOptionChunkMasking) {
sizeParser = NewShakeSizeParser(s.responseBodyIV)
sizeParser = NewShakeSizeParser(s.responseBodyIV[:])
}
switch request.Security {
case protocol.SecurityType_NONE:
@ -332,21 +332,21 @@ func (s *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writ
return buf.NewWriter(s.responseWriter)
case protocol.SecurityType_AES128_GCM:
block, _ := aes.NewCipher(s.responseBodyKey)
block, _ := aes.NewCipher(s.responseBodyKey[:])
aead, _ := cipher.NewGCM(block)
auth := &crypto.AEADAuthenticator{
AEAD: aead,
NonceGenerator: GenerateChunkNonce(s.responseBodyIV, uint32(aead.NonceSize())),
NonceGenerator: GenerateChunkNonce(s.responseBodyIV[:], uint32(aead.NonceSize())),
AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
}
return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType())
case protocol.SecurityType_CHACHA20_POLY1305:
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(s.responseBodyKey))
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(s.responseBodyKey[:]))
auth := &crypto.AEADAuthenticator{
AEAD: aead,
NonceGenerator: GenerateChunkNonce(s.responseBodyIV, uint32(aead.NonceSize())),
NonceGenerator: GenerateChunkNonce(s.responseBodyIV[:], uint32(aead.NonceSize())),
AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
}
return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType())

View File

@ -97,7 +97,7 @@ func (v *userByEmail) Remove(email string) bool {
type Handler struct {
policyManager core.PolicyManager
inboundHandlerManager core.InboundHandlerManager
clients protocol.UserValidator
clients *vmess.TimedUserValidator
usersByEmail *userByEmail
detours *DetourConfig
sessionHistory *encoding.SessionHistory

View File

@ -42,7 +42,7 @@ type indexTimePair struct {
timeInc uint32
}
func NewTimedUserValidator(hasher protocol.IDHash) protocol.UserValidator {
func NewTimedUserValidator(hasher protocol.IDHash) *TimedUserValidator {
tuv := &TimedUserValidator{
users: make([]*user, 0, 16),
userHash: make(map[[16]byte]indexTimePair, 1024),