Skip to content

Commit 166826c

Browse files
xiaokangwangnicholascw
authored andcommitted
Drain Connection with invalid checksum before closing. Emergency fix for weakness described in #2523
1 parent af9999f commit 166826c

File tree

2 files changed

+22
-1
lines changed

2 files changed

+22
-1
lines changed

common/dice/dice.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ func Roll(n int) int {
1515
return rand.Intn(n)
1616
}
1717

18+
// Roll returns a non-negative number between 0 (inclusive) and n (exclusive).
19+
func RollDeterministic(n int, seed int64) int {
20+
if n == 1 {
21+
return 0
22+
}
23+
return rand.New(rand.NewSource(seed)).Intn(n)
24+
}
25+
1826
// RollUint16 returns a random uint16 value.
1927
func RollUint16() uint16 {
2028
return uint16(rand.Intn(65536))

proxy/vmess/encoding/server.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import (
55
"encoding/binary"
66
"hash/fnv"
77
"io"
8+
"io/ioutil"
89
"sync"
910
"time"
11+
"v2ray.com/core/common/dice"
1012

1113
"golang.org/x/crypto/chacha20poly1305"
1214

@@ -194,7 +196,13 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
194196
expectedHash := binary.BigEndian.Uint32(buffer.BytesFrom(-4))
195197

196198
if actualHash != expectedHash {
197-
return nil, newError("invalid auth")
199+
//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")
198206
}
199207

200208
if request.Address == nil {
@@ -347,3 +355,8 @@ func (s *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writ
347355
panic("Unknown security type.")
348356
}
349357
}
358+
359+
func (s *ServerSession) DrainConnN(reader io.Reader, n int) error {
360+
_, err := io.CopyN(ioutil.Discard, reader, int64(n))
361+
return err
362+
}

0 commit comments

Comments
 (0)