mirror of https://github.com/v2ray/v2ray-core
update frame header masking strategy
parent
104446afdf
commit
3c032f0d53
|
@ -4,6 +4,7 @@ import (
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/sha3"
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
"v2ray.com/core/common/errors"
|
"v2ray.com/core/common/errors"
|
||||||
|
@ -67,11 +68,56 @@ func (v *AEADAuthenticator) Seal(dst, plainText []byte) ([]byte, error) {
|
||||||
return v.AEAD.Seal(dst, iv, plainText, additionalData), nil
|
return v.AEAD.Seal(dst, iv, plainText, additionalData), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Uint16Generator interface {
|
||||||
|
Next() uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
type StaticUint16Generator uint16
|
||||||
|
|
||||||
|
func (g StaticUint16Generator) Next() uint16 {
|
||||||
|
return uint16(g)
|
||||||
|
}
|
||||||
|
|
||||||
|
type MultiplyUint16Generator struct {
|
||||||
|
base uint16
|
||||||
|
value uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMultiplyUint16Generator(base uint16) *MultiplyUint16Generator {
|
||||||
|
return &MultiplyUint16Generator{
|
||||||
|
base: base,
|
||||||
|
value: 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *MultiplyUint16Generator) Next() uint16 {
|
||||||
|
g.value *= g.base
|
||||||
|
return g.value
|
||||||
|
}
|
||||||
|
|
||||||
|
type ShakeUint16Generator struct {
|
||||||
|
shake sha3.ShakeHash
|
||||||
|
buffer [2]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewShakeUint16Generator(nonce []byte) *ShakeUint16Generator {
|
||||||
|
shake := sha3.NewShake128()
|
||||||
|
shake.Write(nonce)
|
||||||
|
return &ShakeUint16Generator{
|
||||||
|
shake: shake,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *ShakeUint16Generator) Next() uint16 {
|
||||||
|
g.shake.Read(g.buffer[:])
|
||||||
|
return serial.BytesToUint16(g.buffer[:])
|
||||||
|
}
|
||||||
|
|
||||||
type AuthenticationReader struct {
|
type AuthenticationReader struct {
|
||||||
auth Authenticator
|
auth Authenticator
|
||||||
buffer *buf.Buffer
|
buffer *buf.Buffer
|
||||||
reader io.Reader
|
reader io.Reader
|
||||||
sizeMask uint16
|
sizeMask Uint16Generator
|
||||||
|
|
||||||
chunk []byte
|
chunk []byte
|
||||||
}
|
}
|
||||||
|
@ -80,7 +126,7 @@ const (
|
||||||
readerBufferSize = 32 * 1024
|
readerBufferSize = 32 * 1024
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewAuthenticationReader(auth Authenticator, reader io.Reader, sizeMask uint16) *AuthenticationReader {
|
func NewAuthenticationReader(auth Authenticator, reader io.Reader, sizeMask Uint16Generator) *AuthenticationReader {
|
||||||
return &AuthenticationReader{
|
return &AuthenticationReader{
|
||||||
auth: auth,
|
auth: auth,
|
||||||
buffer: buf.NewLocal(readerBufferSize),
|
buffer: buf.NewLocal(readerBufferSize),
|
||||||
|
@ -89,11 +135,11 @@ func NewAuthenticationReader(auth Authenticator, reader io.Reader, sizeMask uint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *AuthenticationReader) NextChunk() error {
|
func (v *AuthenticationReader) NextChunk(mask uint16) error {
|
||||||
if v.buffer.Len() < 2 {
|
if v.buffer.Len() < 2 {
|
||||||
return errInsufficientBuffer
|
return errInsufficientBuffer
|
||||||
}
|
}
|
||||||
size := int(serial.BytesToUint16(v.buffer.BytesTo(2)) ^ v.sizeMask)
|
size := int(serial.BytesToUint16(v.buffer.BytesTo(2)) ^ mask)
|
||||||
if size > v.buffer.Len()-2 {
|
if size > v.buffer.Len()-2 {
|
||||||
return errInsufficientBuffer
|
return errInsufficientBuffer
|
||||||
}
|
}
|
||||||
|
@ -136,8 +182,9 @@ func (v *AuthenticationReader) EnsureChunk() error {
|
||||||
atHead = true
|
atHead = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mask := v.sizeMask.Next()
|
||||||
for {
|
for {
|
||||||
err := v.NextChunk()
|
err := v.NextChunk(mask)
|
||||||
if err != errInsufficientBuffer {
|
if err != errInsufficientBuffer {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -173,10 +220,10 @@ type AuthenticationWriter struct {
|
||||||
auth Authenticator
|
auth Authenticator
|
||||||
buffer []byte
|
buffer []byte
|
||||||
writer io.Writer
|
writer io.Writer
|
||||||
sizeMask uint16
|
sizeMask Uint16Generator
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAuthenticationWriter(auth Authenticator, writer io.Writer, sizeMask uint16) *AuthenticationWriter {
|
func NewAuthenticationWriter(auth Authenticator, writer io.Writer, sizeMask Uint16Generator) *AuthenticationWriter {
|
||||||
return &AuthenticationWriter{
|
return &AuthenticationWriter{
|
||||||
auth: auth,
|
auth: auth,
|
||||||
buffer: make([]byte, 32*1024),
|
buffer: make([]byte, 32*1024),
|
||||||
|
@ -191,7 +238,7 @@ func (v *AuthenticationWriter) Write(b []byte) (int, error) {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
size := uint16(len(cipherChunk)) ^ v.sizeMask
|
size := uint16(len(cipherChunk)) ^ v.sizeMask.Next()
|
||||||
serial.Uint16ToBytes(size, v.buffer[:0])
|
serial.Uint16ToBytes(size, v.buffer[:0])
|
||||||
_, err = v.writer.Write(v.buffer[:2+len(cipherChunk)])
|
_, err = v.writer.Write(v.buffer[:2+len(cipherChunk)])
|
||||||
return len(b), err
|
return len(b), err
|
||||||
|
|
|
@ -10,15 +10,12 @@ import (
|
||||||
|
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
. "v2ray.com/core/common/crypto"
|
. "v2ray.com/core/common/crypto"
|
||||||
"v2ray.com/core/common/dice"
|
|
||||||
"v2ray.com/core/testing/assert"
|
"v2ray.com/core/testing/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAuthenticationReaderWriter(t *testing.T) {
|
func TestAuthenticationReaderWriter(t *testing.T) {
|
||||||
assert := assert.On(t)
|
assert := assert.On(t)
|
||||||
|
|
||||||
sizeMask := uint16(dice.Roll(65536))
|
|
||||||
|
|
||||||
key := make([]byte, 16)
|
key := make([]byte, 16)
|
||||||
rand.Read(key)
|
rand.Read(key)
|
||||||
block, err := aes.NewCipher(key)
|
block, err := aes.NewCipher(key)
|
||||||
|
@ -40,7 +37,7 @@ func TestAuthenticationReaderWriter(t *testing.T) {
|
||||||
Content: iv,
|
Content: iv,
|
||||||
},
|
},
|
||||||
AdditionalDataGenerator: &NoOpBytesGenerator{},
|
AdditionalDataGenerator: &NoOpBytesGenerator{},
|
||||||
}, cache, sizeMask)
|
}, cache, NewShakeUint16Generator([]byte{'a'}))
|
||||||
|
|
||||||
nBytes, err := writer.Write(payload)
|
nBytes, err := writer.Write(payload)
|
||||||
assert.Error(err).IsNil()
|
assert.Error(err).IsNil()
|
||||||
|
@ -55,7 +52,7 @@ func TestAuthenticationReaderWriter(t *testing.T) {
|
||||||
Content: iv,
|
Content: iv,
|
||||||
},
|
},
|
||||||
AdditionalDataGenerator: &NoOpBytesGenerator{},
|
AdditionalDataGenerator: &NoOpBytesGenerator{},
|
||||||
}, cache, sizeMask)
|
}, cache, NewShakeUint16Generator([]byte{'a'}))
|
||||||
|
|
||||||
actualPayload := make([]byte, 16*1024)
|
actualPayload := make([]byte, 16*1024)
|
||||||
nBytes, err = reader.Read(actualPayload)
|
nBytes, err = reader.Read(actualPayload)
|
||||||
|
@ -70,8 +67,6 @@ func TestAuthenticationReaderWriter(t *testing.T) {
|
||||||
func TestAuthenticationReaderWriterPartial(t *testing.T) {
|
func TestAuthenticationReaderWriterPartial(t *testing.T) {
|
||||||
assert := assert.On(t)
|
assert := assert.On(t)
|
||||||
|
|
||||||
sizeMask := uint16(dice.Roll(65536))
|
|
||||||
|
|
||||||
key := make([]byte, 16)
|
key := make([]byte, 16)
|
||||||
rand.Read(key)
|
rand.Read(key)
|
||||||
block, err := aes.NewCipher(key)
|
block, err := aes.NewCipher(key)
|
||||||
|
@ -93,7 +88,7 @@ func TestAuthenticationReaderWriterPartial(t *testing.T) {
|
||||||
Content: iv,
|
Content: iv,
|
||||||
},
|
},
|
||||||
AdditionalDataGenerator: &NoOpBytesGenerator{},
|
AdditionalDataGenerator: &NoOpBytesGenerator{},
|
||||||
}, cache, sizeMask)
|
}, cache, NewShakeUint16Generator([]byte{'a', 'b'}))
|
||||||
|
|
||||||
writer.Write([]byte{'a', 'b', 'c', 'd'})
|
writer.Write([]byte{'a', 'b', 'c', 'd'})
|
||||||
|
|
||||||
|
@ -123,7 +118,7 @@ func TestAuthenticationReaderWriterPartial(t *testing.T) {
|
||||||
Content: iv,
|
Content: iv,
|
||||||
},
|
},
|
||||||
AdditionalDataGenerator: &NoOpBytesGenerator{},
|
AdditionalDataGenerator: &NoOpBytesGenerator{},
|
||||||
}, pr, sizeMask)
|
}, pr, NewShakeUint16Generator([]byte{'a', 'b'}))
|
||||||
|
|
||||||
actualPayload := make([]byte, 7*1024)
|
actualPayload := make([]byte, 7*1024)
|
||||||
nBytes, err = reader.Read(actualPayload)
|
nBytes, err = reader.Read(actualPayload)
|
||||||
|
|
|
@ -24,8 +24,7 @@ const (
|
||||||
// RequestOptionConnectionReuse indicates client side expects to reuse the connection.
|
// RequestOptionConnectionReuse indicates client side expects to reuse the connection.
|
||||||
RequestOptionConnectionReuse = RequestOption(0x02)
|
RequestOptionConnectionReuse = RequestOption(0x02)
|
||||||
|
|
||||||
// RequestOptionCompressedStream indicates request payload is compressed.
|
RequestOptionChunkMasking = RequestOption(0x04)
|
||||||
RequestOptionCompressedStream = RequestOption(0x04)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (v RequestOption) Has(option RequestOption) bool {
|
func (v RequestOption) Has(option RequestOption) bool {
|
||||||
|
|
|
@ -119,6 +119,10 @@ func (v *ClientSession) EncodeRequestHeader(header *protocol.RequestHeader, writ
|
||||||
|
|
||||||
func (v *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, writer io.Writer) buf.Writer {
|
func (v *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, writer io.Writer) buf.Writer {
|
||||||
var authWriter io.Writer
|
var authWriter io.Writer
|
||||||
|
var sizeMask crypto.Uint16Generator = crypto.StaticUint16Generator(0)
|
||||||
|
if request.Option.Has(protocol.RequestOptionChunkMasking) {
|
||||||
|
sizeMask = getSizeMask(v.requestBodyIV)
|
||||||
|
}
|
||||||
if request.Security.Is(protocol.SecurityType_NONE) {
|
if request.Security.Is(protocol.SecurityType_NONE) {
|
||||||
if request.Option.Has(protocol.RequestOptionChunkStream) {
|
if request.Option.Has(protocol.RequestOptionChunkStream) {
|
||||||
auth := &crypto.AEADAuthenticator{
|
auth := &crypto.AEADAuthenticator{
|
||||||
|
@ -126,7 +130,7 @@ func (v *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, write
|
||||||
NonceGenerator: crypto.NoOpBytesGenerator{},
|
NonceGenerator: crypto.NoOpBytesGenerator{},
|
||||||
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
||||||
}
|
}
|
||||||
authWriter = crypto.NewAuthenticationWriter(auth, writer, getSizeMask(v.requestBodyIV))
|
authWriter = crypto.NewAuthenticationWriter(auth, writer, sizeMask)
|
||||||
} else {
|
} else {
|
||||||
authWriter = writer
|
authWriter = writer
|
||||||
}
|
}
|
||||||
|
@ -139,7 +143,7 @@ func (v *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, write
|
||||||
NonceGenerator: crypto.NoOpBytesGenerator{},
|
NonceGenerator: crypto.NoOpBytesGenerator{},
|
||||||
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
||||||
}
|
}
|
||||||
authWriter = crypto.NewAuthenticationWriter(auth, cryptionWriter, 0)
|
authWriter = crypto.NewAuthenticationWriter(auth, cryptionWriter, sizeMask)
|
||||||
} else {
|
} else {
|
||||||
authWriter = cryptionWriter
|
authWriter = cryptionWriter
|
||||||
}
|
}
|
||||||
|
@ -155,7 +159,7 @@ func (v *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, write
|
||||||
},
|
},
|
||||||
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
||||||
}
|
}
|
||||||
authWriter = crypto.NewAuthenticationWriter(auth, writer, getSizeMask(v.requestBodyIV))
|
authWriter = crypto.NewAuthenticationWriter(auth, writer, sizeMask)
|
||||||
} else if request.Security.Is(protocol.SecurityType_CHACHA20_POLY1305) {
|
} else if request.Security.Is(protocol.SecurityType_CHACHA20_POLY1305) {
|
||||||
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(v.requestBodyKey))
|
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(v.requestBodyKey))
|
||||||
|
|
||||||
|
@ -167,7 +171,7 @@ func (v *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, write
|
||||||
},
|
},
|
||||||
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
||||||
}
|
}
|
||||||
authWriter = crypto.NewAuthenticationWriter(auth, writer, getSizeMask(v.requestBodyIV))
|
authWriter = crypto.NewAuthenticationWriter(auth, writer, sizeMask)
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf.NewWriter(authWriter)
|
return buf.NewWriter(authWriter)
|
||||||
|
@ -214,14 +218,18 @@ func (v *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.Respon
|
||||||
|
|
||||||
func (v *ClientSession) DecodeResponseBody(request *protocol.RequestHeader, reader io.Reader) buf.Reader {
|
func (v *ClientSession) DecodeResponseBody(request *protocol.RequestHeader, reader io.Reader) buf.Reader {
|
||||||
var authReader io.Reader
|
var authReader io.Reader
|
||||||
|
var sizeMask crypto.Uint16Generator = crypto.StaticUint16Generator(0)
|
||||||
|
if request.Option.Has(protocol.RequestOptionChunkMasking) {
|
||||||
|
sizeMask = getSizeMask(v.responseBodyIV)
|
||||||
|
}
|
||||||
if request.Security.Is(protocol.SecurityType_NONE) {
|
if request.Security.Is(protocol.SecurityType_NONE) {
|
||||||
if request.Option.Has(protocol.RequestOptionChunkStream) {
|
if request.Option.Has(protocol.RequestOptionChunkStream) {
|
||||||
auth := &crypto.AEADAuthenticator{
|
auth := &crypto.AEADAuthenticator{
|
||||||
AEAD: new(FnvAuthenticator),
|
AEAD: NoOpAuthenticator{},
|
||||||
NonceGenerator: crypto.NoOpBytesGenerator{},
|
NonceGenerator: crypto.NoOpBytesGenerator{},
|
||||||
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
||||||
}
|
}
|
||||||
authReader = crypto.NewAuthenticationReader(auth, reader, getSizeMask(v.responseBodyIV))
|
authReader = crypto.NewAuthenticationReader(auth, reader, sizeMask)
|
||||||
} else {
|
} else {
|
||||||
authReader = reader
|
authReader = reader
|
||||||
}
|
}
|
||||||
|
@ -232,7 +240,7 @@ func (v *ClientSession) DecodeResponseBody(request *protocol.RequestHeader, read
|
||||||
NonceGenerator: crypto.NoOpBytesGenerator{},
|
NonceGenerator: crypto.NoOpBytesGenerator{},
|
||||||
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
||||||
}
|
}
|
||||||
authReader = crypto.NewAuthenticationReader(auth, v.responseReader, 0)
|
authReader = crypto.NewAuthenticationReader(auth, v.responseReader, sizeMask)
|
||||||
} else {
|
} else {
|
||||||
authReader = v.responseReader
|
authReader = v.responseReader
|
||||||
}
|
}
|
||||||
|
@ -248,7 +256,7 @@ func (v *ClientSession) DecodeResponseBody(request *protocol.RequestHeader, read
|
||||||
},
|
},
|
||||||
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
||||||
}
|
}
|
||||||
authReader = crypto.NewAuthenticationReader(auth, reader, getSizeMask(v.responseBodyIV))
|
authReader = crypto.NewAuthenticationReader(auth, reader, sizeMask)
|
||||||
} else if request.Security.Is(protocol.SecurityType_CHACHA20_POLY1305) {
|
} else if request.Security.Is(protocol.SecurityType_CHACHA20_POLY1305) {
|
||||||
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(v.responseBodyKey))
|
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(v.responseBodyKey))
|
||||||
|
|
||||||
|
@ -260,7 +268,7 @@ func (v *ClientSession) DecodeResponseBody(request *protocol.RequestHeader, read
|
||||||
},
|
},
|
||||||
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
||||||
}
|
}
|
||||||
authReader = crypto.NewAuthenticationReader(auth, reader, getSizeMask(v.responseBodyIV))
|
authReader = crypto.NewAuthenticationReader(auth, reader, sizeMask)
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf.NewReader(authReader)
|
return buf.NewReader(authReader)
|
||||||
|
|
|
@ -94,12 +94,8 @@ func (h *SessionHistory) run() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSizeMask(b []byte) uint16 {
|
func getSizeMask(b []byte) crypto.Uint16Generator {
|
||||||
mask := uint16(0)
|
return crypto.NewShakeUint16Generator(b)
|
||||||
for i := 0; i < len(b); i += 2 {
|
|
||||||
mask ^= serial.BytesToUint16(b[i : i+2])
|
|
||||||
}
|
|
||||||
return mask
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServerSession struct {
|
type ServerSession struct {
|
||||||
|
@ -245,6 +241,10 @@ func (v *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
|
||||||
|
|
||||||
func (v *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reader io.Reader) buf.Reader {
|
func (v *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reader io.Reader) buf.Reader {
|
||||||
var authReader io.Reader
|
var authReader io.Reader
|
||||||
|
var sizeMask crypto.Uint16Generator = crypto.StaticUint16Generator(0)
|
||||||
|
if request.Option.Has(protocol.RequestOptionChunkMasking) {
|
||||||
|
sizeMask = getSizeMask(v.requestBodyIV)
|
||||||
|
}
|
||||||
if request.Security.Is(protocol.SecurityType_NONE) {
|
if request.Security.Is(protocol.SecurityType_NONE) {
|
||||||
if request.Option.Has(protocol.RequestOptionChunkStream) {
|
if request.Option.Has(protocol.RequestOptionChunkStream) {
|
||||||
auth := &crypto.AEADAuthenticator{
|
auth := &crypto.AEADAuthenticator{
|
||||||
|
@ -252,7 +252,7 @@ func (v *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade
|
||||||
NonceGenerator: crypto.NoOpBytesGenerator{},
|
NonceGenerator: crypto.NoOpBytesGenerator{},
|
||||||
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
||||||
}
|
}
|
||||||
authReader = crypto.NewAuthenticationReader(auth, reader, getSizeMask(v.requestBodyIV))
|
authReader = crypto.NewAuthenticationReader(auth, reader, sizeMask)
|
||||||
} else {
|
} else {
|
||||||
authReader = reader
|
authReader = reader
|
||||||
}
|
}
|
||||||
|
@ -265,7 +265,7 @@ func (v *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade
|
||||||
NonceGenerator: crypto.NoOpBytesGenerator{},
|
NonceGenerator: crypto.NoOpBytesGenerator{},
|
||||||
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
||||||
}
|
}
|
||||||
authReader = crypto.NewAuthenticationReader(auth, cryptionReader, 0)
|
authReader = crypto.NewAuthenticationReader(auth, cryptionReader, sizeMask)
|
||||||
} else {
|
} else {
|
||||||
authReader = cryptionReader
|
authReader = cryptionReader
|
||||||
}
|
}
|
||||||
|
@ -281,7 +281,7 @@ func (v *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade
|
||||||
},
|
},
|
||||||
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
||||||
}
|
}
|
||||||
authReader = crypto.NewAuthenticationReader(auth, reader, getSizeMask(v.requestBodyIV))
|
authReader = crypto.NewAuthenticationReader(auth, reader, sizeMask)
|
||||||
} else if request.Security.Is(protocol.SecurityType_CHACHA20_POLY1305) {
|
} else if request.Security.Is(protocol.SecurityType_CHACHA20_POLY1305) {
|
||||||
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(v.requestBodyKey))
|
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(v.requestBodyKey))
|
||||||
|
|
||||||
|
@ -293,7 +293,7 @@ func (v *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade
|
||||||
},
|
},
|
||||||
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
||||||
}
|
}
|
||||||
authReader = crypto.NewAuthenticationReader(auth, reader, getSizeMask(v.requestBodyIV))
|
authReader = crypto.NewAuthenticationReader(auth, reader, sizeMask)
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf.NewReader(authReader)
|
return buf.NewReader(authReader)
|
||||||
|
@ -318,14 +318,18 @@ func (v *ServerSession) EncodeResponseHeader(header *protocol.ResponseHeader, wr
|
||||||
|
|
||||||
func (v *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writer io.Writer) buf.Writer {
|
func (v *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writer io.Writer) buf.Writer {
|
||||||
var authWriter io.Writer
|
var authWriter io.Writer
|
||||||
|
var sizeMask crypto.Uint16Generator = crypto.StaticUint16Generator(0)
|
||||||
|
if request.Option.Has(protocol.RequestOptionChunkMasking) {
|
||||||
|
sizeMask = getSizeMask(v.responseBodyIV)
|
||||||
|
}
|
||||||
if request.Security.Is(protocol.SecurityType_NONE) {
|
if request.Security.Is(protocol.SecurityType_NONE) {
|
||||||
if request.Option.Has(protocol.RequestOptionChunkStream) {
|
if request.Option.Has(protocol.RequestOptionChunkStream) {
|
||||||
auth := &crypto.AEADAuthenticator{
|
auth := &crypto.AEADAuthenticator{
|
||||||
AEAD: new(FnvAuthenticator),
|
AEAD: NoOpAuthenticator{},
|
||||||
NonceGenerator: crypto.NoOpBytesGenerator{},
|
NonceGenerator: crypto.NoOpBytesGenerator{},
|
||||||
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
||||||
}
|
}
|
||||||
authWriter = crypto.NewAuthenticationWriter(auth, writer, getSizeMask(v.responseBodyIV))
|
authWriter = crypto.NewAuthenticationWriter(auth, writer, sizeMask)
|
||||||
} else {
|
} else {
|
||||||
authWriter = writer
|
authWriter = writer
|
||||||
}
|
}
|
||||||
|
@ -336,7 +340,7 @@ func (v *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writ
|
||||||
NonceGenerator: crypto.NoOpBytesGenerator{},
|
NonceGenerator: crypto.NoOpBytesGenerator{},
|
||||||
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
||||||
}
|
}
|
||||||
authWriter = crypto.NewAuthenticationWriter(auth, v.responseWriter, 0)
|
authWriter = crypto.NewAuthenticationWriter(auth, v.responseWriter, sizeMask)
|
||||||
} else {
|
} else {
|
||||||
authWriter = v.responseWriter
|
authWriter = v.responseWriter
|
||||||
}
|
}
|
||||||
|
@ -352,7 +356,7 @@ func (v *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writ
|
||||||
},
|
},
|
||||||
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
||||||
}
|
}
|
||||||
authWriter = crypto.NewAuthenticationWriter(auth, writer, getSizeMask(v.responseBodyIV))
|
authWriter = crypto.NewAuthenticationWriter(auth, writer, sizeMask)
|
||||||
} else if request.Security.Is(protocol.SecurityType_CHACHA20_POLY1305) {
|
} else if request.Security.Is(protocol.SecurityType_CHACHA20_POLY1305) {
|
||||||
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(v.responseBodyKey))
|
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(v.responseBodyKey))
|
||||||
|
|
||||||
|
@ -364,7 +368,7 @@ func (v *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writ
|
||||||
},
|
},
|
||||||
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
AdditionalDataGenerator: crypto.NoOpBytesGenerator{},
|
||||||
}
|
}
|
||||||
authWriter = crypto.NewAuthenticationWriter(auth, writer, getSizeMask(v.responseBodyIV))
|
authWriter = crypto.NewAuthenticationWriter(auth, writer, sizeMask)
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf.NewWriter(authWriter)
|
return buf.NewWriter(authWriter)
|
||||||
|
|
|
@ -93,6 +93,10 @@ 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) {
|
||||||
|
request.Option.Set(protocol.RequestOptionChunkMasking)
|
||||||
|
}
|
||||||
|
|
||||||
conn.SetReusable(true)
|
conn.SetReusable(true)
|
||||||
if conn.Reusable() { // Conn reuse may be disabled on transportation layer
|
if conn.Reusable() { // Conn reuse may be disabled on transportation layer
|
||||||
request.Option.Set(protocol.RequestOptionConnectionReuse)
|
request.Option.Set(protocol.RequestOptionConnectionReuse)
|
||||||
|
|
Loading…
Reference in New Issue