@@ -125,15 +125,37 @@ func parseSecurityType(b byte) protocol.SecurityType {
125125// DecodeRequestHeader decodes and returns (if successful) a RequestHeader from an input stream.
126126func (s * ServerSession ) DecodeRequestHeader (reader io.Reader ) (* protocol.RequestHeader , error ) {
127127 buffer := buf .New ()
128- defer buffer .Release ()
128+ behaviorRand := dice .NewDeterministicDice (int64 (s .userValidator .GetBehaviorSeed ()))
129+ BaseDrainSize := behaviorRand .Roll (3266 )
130+ RandDrainMax := behaviorRand .Roll (64 ) + 1
131+ RandDrainRolled := dice .Roll (RandDrainMax )
132+ DrainSize := BaseDrainSize + 16 + 38 + RandDrainRolled
133+ readSizeRemain := DrainSize
134+
135+ drainConnection := func (e error ) error {
136+ //We read a deterministic generated length of data before closing the connection to offset padding read pattern
137+ readSizeRemain -= int (buffer .Len ())
138+ if readSizeRemain > 0 {
139+ err := s .DrainConnN (reader , readSizeRemain )
140+ if err != nil {
141+ return newError ("failed to drain connection DrainSize = " , BaseDrainSize , " " , RandDrainMax , " " , RandDrainRolled ).Base (err ).Base (e )
142+ }
143+ return newError ("connection drained DrainSize = " , BaseDrainSize , " " , RandDrainMax , " " , RandDrainRolled ).Base (e )
144+ }
145+ return e
146+ }
147+
148+ defer func () {
149+ buffer .Release ()
150+ }()
129151
130152 if _ , err := buffer .ReadFullFrom (reader , protocol .IDBytesLen ); err != nil {
131153 return nil , newError ("failed to read request header" ).Base (err )
132154 }
133155
134156 user , timestamp , valid := s .userValidator .Get (buffer .Bytes ())
135157 if ! valid {
136- return nil , newError ("invalid user" )
158+ return nil , drainConnection ( newError ("invalid user" ) )
137159 }
138160
139161 iv := hashTimestamp (md5 .New (), timestamp )
@@ -142,6 +164,7 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
142164 aesStream := crypto .NewAesDecryptionStream (vmessAccount .ID .CmdKey (), iv [:])
143165 decryptor := crypto .NewCryptionReader (aesStream , reader )
144166
167+ readSizeRemain -= int (buffer .Len ())
145168 buffer .Clear ()
146169 if _ , err := buffer .ReadFullFrom (decryptor , 38 ); err != nil {
147170 return nil , newError ("failed to read request header" ).Base (err )
@@ -159,7 +182,7 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
159182 sid .key = s .requestBodyKey
160183 sid .nonce = s .requestBodyIV
161184 if ! s .sessionHistory .addIfNotExits (sid ) {
162- return nil , newError ("duplicated session id, possibly under replay attack" )
185+ return nil , drainConnection ( newError ("duplicated session id, possibly under replay attack" ) )
163186 }
164187
165188 s .responseHeader = buffer .Byte (33 ) // 1 byte
@@ -197,12 +220,7 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
197220
198221 if actualHash != expectedHash {
199222 //It is possible that we are under attack described in https://github.com/v2ray/v2ray-core/issues/2523
200- //We read a deterministic generated length of data before closing the connection to offset padding read pattern
201- drainSum := dice .RollDeterministic (48 , int64 (actualHash ))
202- if err := s .DrainConnN (reader , drainSum ); err != nil {
203- return nil , newError ("invalid auth, failed to drain connection" ).Base (err )
204- }
205- return nil , newError ("invalid auth, connection drained" )
223+ return nil , drainConnection (newError ("invalid auth" ))
206224 }
207225
208226 if request .Address == nil {
0 commit comments