Drain Connection with invalid checksum before closing. Emergency fix for weakness described in https://github.com/v2ray/v2ray-core/issues/2523

pull/2531/head
Shelikhoo 5 years ago committed by Nicholas Wang
parent af9999f861
commit 166826c478
No known key found for this signature in database
GPG Key ID: F20CA399C9BD9100

@ -15,6 +15,14 @@ func Roll(n int) int {
return rand.Intn(n)
}
// Roll returns a non-negative number between 0 (inclusive) and n (exclusive).
func RollDeterministic(n int, seed int64) int {
if n == 1 {
return 0
}
return rand.New(rand.NewSource(seed)).Intn(n)
}
// RollUint16 returns a random uint16 value.
func RollUint16() uint16 {
return uint16(rand.Intn(65536))

@ -5,8 +5,10 @@ import (
"encoding/binary"
"hash/fnv"
"io"
"io/ioutil"
"sync"
"time"
"v2ray.com/core/common/dice"
"golang.org/x/crypto/chacha20poly1305"
@ -194,7 +196,13 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
expectedHash := binary.BigEndian.Uint32(buffer.BytesFrom(-4))
if actualHash != expectedHash {
return nil, newError("invalid auth")
//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")
}
if request.Address == nil {
@ -347,3 +355,8 @@ func (s *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writ
panic("Unknown security type.")
}
}
func (s *ServerSession) DrainConnN(reader io.Reader, n int) error {
_, err := io.CopyN(ioutil.Discard, reader, int64(n))
return err
}

Loading…
Cancel
Save