|
|
@@ -125,7 +125,26 @@ func parseSecurityType(b byte) protocol.SecurityType {
|
|
|
// DecodeRequestHeader decodes and returns (if successful) a RequestHeader from an input stream.
|
|
|
func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.RequestHeader, error) {
|
|
|
buffer := buf.New()
|
|
|
- defer buffer.Release()
|
|
|
+ behaviorRand := dice.NewDeterministicDice(int64(s.userValidator.GetBehaviorSeed()))
|
|
|
+ DrainSize := behaviorRand.Roll(387) + 16 + 38
|
|
|
+ readSizeRemain := DrainSize
|
|
|
+
|
|
|
+ drainConnection := func(e error) error {
|
|
|
+ //We read a deterministic generated length of data before closing the connection to offset padding read pattern
|
|
|
+ readSizeRemain -= int(buffer.Len())
|
|
|
+ if readSizeRemain > 0 {
|
|
|
+ err := s.DrainConnN(reader, readSizeRemain)
|
|
|
+ if err != nil {
|
|
|
+ return newError("failed to drain connection").Base(err).Base(e)
|
|
|
+ }
|
|
|
+ return newError("connection drained DrainSize = ", DrainSize).Base(e)
|
|
|
+ }
|
|
|
+ return e
|
|
|
+ }
|
|
|
+
|
|
|
+ defer func() {
|
|
|
+ buffer.Release()
|
|
|
+ }()
|
|
|
|
|
|
if _, err := buffer.ReadFullFrom(reader, protocol.IDBytesLen); err != nil {
|
|
|
return nil, newError("failed to read request header").Base(err)
|
|
|
@@ -133,7 +152,8 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
|
|
|
|
|
|
user, timestamp, valid := s.userValidator.Get(buffer.Bytes())
|
|
|
if !valid {
|
|
|
- return nil, newError("invalid user")
|
|
|
+ //It is possible that we are under attack described in https://github.com/v2ray/v2ray-core/issues/2523
|
|
|
+ return nil, drainConnection(newError("invalid user"))
|
|
|
}
|
|
|
|
|
|
iv := hashTimestamp(md5.New(), timestamp)
|
|
|
@@ -142,6 +162,7 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
|
|
|
aesStream := crypto.NewAesDecryptionStream(vmessAccount.ID.CmdKey(), iv[:])
|
|
|
decryptor := crypto.NewCryptionReader(aesStream, reader)
|
|
|
|
|
|
+ readSizeRemain -= int(buffer.Len())
|
|
|
buffer.Clear()
|
|
|
if _, err := buffer.ReadFullFrom(decryptor, 38); err != nil {
|
|
|
return nil, newError("failed to read request header").Base(err)
|
|
|
@@ -197,12 +218,7 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
|
|
|
|
|
|
if actualHash != expectedHash {
|
|
|
//It is possible that we are under attack described in https://github.com/v2ray/v2ray-core/issues/2523
|
|
|
- //We read a deterministic generated length of data before closing the connection to offset padding read pattern
|
|
|
- drainSum := dice.RollDeterministic(48, int64(actualHash))
|
|
|
- if err := s.DrainConnN(reader, drainSum); err != nil {
|
|
|
- return nil, newError("invalid auth, failed to drain connection").Base(err)
|
|
|
- }
|
|
|
- return nil, newError("invalid auth, connection drained")
|
|
|
+ return nil, drainConnection(newError("invalid auth"))
|
|
|
}
|
|
|
|
|
|
if request.Address == nil {
|