diff --git a/transport/vless/encryption/client.go b/transport/vless/encryption/client.go index c5a3df98..b6e2c19d 100644 --- a/transport/vless/encryption/client.go +++ b/transport/vless/encryption/client.go @@ -115,9 +115,9 @@ func (i *ClientInstance) Handshake(conn net.Conn) (net.Conn, error) { if _, err := c.Conn.Write(clientHello); err != nil { return nil, err } - // client can send more padding / NFS AEAD messages if needed + // client can send more paddings / NFS AEAD messages if needed - _, t, l, err := ReadAndDiscardPaddings(c.Conn) + _, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before server hello if err != nil { return nil, err } @@ -201,9 +201,9 @@ func (c *ClientConn) Read(b []byte) (int, error) { return 0, nil } if c.peerAead == nil { - _, t, l, err := ReadAndDiscardPaddings(c.Conn) + _, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before random hello if err != nil { - if c.instance != nil && strings.HasPrefix(err.Error(), "invalid header: ") { // from 0-RTT + if c.instance != nil && strings.HasPrefix(err.Error(), "invalid header: ") { // 0-RTT's 0-RTT c.instance.Lock() if bytes.Equal(c.ticket, c.instance.ticket) { c.instance.expire = time.Now() // expired diff --git a/transport/vless/encryption/common.go b/transport/vless/encryption/common.go index 2a1a5a00..151a48e4 100644 --- a/transport/vless/encryption/common.go +++ b/transport/vless/encryption/common.go @@ -48,7 +48,7 @@ func DecodeHeader(h []byte) (t byte, l int, err error) { l = 0 } if l < 17 || l > 17000 { // TODO: TLSv1.3 max length - err = fmt.Errorf("invalid header: %v", h[:5]) // relied by client's Read() + err = fmt.Errorf("invalid header: %v", h[:5]) // DO NOT CHANGE: relied by client's Read() } return } diff --git a/transport/vless/encryption/doc.go b/transport/vless/encryption/doc.go index 43fe2c44..900866ec 100644 --- a/transport/vless/encryption/doc.go +++ b/transport/vless/encryption/doc.go @@ -10,4 +10,5 @@ // https://github.com/XTLS/Xray-core/commit/0fd7691d6b28e05922d7a5a9313d97745a51ea63 // https://github.com/XTLS/Xray-core/commit/09cc92c61d9067e0d65c1cae9124664ecfc78f43 // https://github.com/XTLS/Xray-core/commit/2807ee432a1fbeb301815647189eacd650b12a8b +// https://github.com/XTLS/Xray-core/commit/bfe4820f2f086daf639b1957eb23dc13c843cad1 package encryption diff --git a/transport/vless/encryption/server.go b/transport/vless/encryption/server.go index 0e2f4277..f67c9720 100644 --- a/transport/vless/encryption/server.go +++ b/transport/vless/encryption/server.go @@ -97,7 +97,7 @@ func (i *ServerInstance) Handshake(conn net.Conn) (net.Conn, error) { } c := &ServerConn{Conn: conn} - _, t, l, err := ReadAndDiscardPaddings(c.Conn) + _, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before client/ticket hello if err != nil { return nil, err } @@ -117,9 +117,13 @@ func (i *ServerInstance) Handshake(conn net.Conn) (net.Conn, error) { s := i.sessions[[21]byte(peerTicketHello)] i.RUnlock() if s == nil { - noise := make([]byte, randBetween(100, 1000)) - rand.Read(noise) - c.Conn.Write(noise) // make client do new handshake + noises := make([]byte, randBetween(100, 1000)) + var err error + for err == nil { + rand.Read(noises) + _, _, err = DecodeHeader(noises) + } + c.Conn.Write(noises) // make client do new handshake return nil, errors.New("expired ticket") } if _, replay := s.randoms.LoadOrStore([32]byte(peerTicketHello[21:]), true); replay { @@ -169,7 +173,7 @@ func (i *ServerInstance) Handshake(conn net.Conn) (net.Conn, error) { if _, err := c.Conn.Write(serverHello); err != nil { return nil, err } - // server can send more padding / PFS AEAD messages if needed + // server can send more paddings / PFS AEAD messages if needed if i.minutes > 0 { i.Lock() @@ -189,8 +193,8 @@ func (c *ServerConn) Read(b []byte) (int, error) { return 0, nil } if c.peerAead == nil { - if c.peerRandom == nil { // from 1-RTT - _, t, l, err := ReadAndDiscardPaddings(c.Conn) + if c.peerRandom == nil { // 1-RTT's 0-RTT + _, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before ticket hello if err != nil { return 0, err } diff --git a/transport/vless/encryption/xor.go b/transport/vless/encryption/xor.go index bbe489ef..64828eaa 100644 --- a/transport/vless/encryption/xor.go +++ b/transport/vless/encryption/xor.go @@ -22,7 +22,7 @@ func NewXorConn(conn net.Conn, key []byte) *XorConn { //chacha20.NewUnauthenticatedCipher() } -func (c *XorConn) Write(b []byte) (int, error) { // two records at most +func (c *XorConn) Write(b []byte) (int, error) { // whole one/two records if len(b) == 0 { return 0, nil } @@ -34,10 +34,10 @@ func (c *XorConn) Write(b []byte) (int, error) { // two records at most c.ctr = cipher.NewCTR(block, iv) } t, l, _ := DecodeHeader(b) - if t != 23 { - l += 10 // 5+l+5 - } else { + if t == 23 { // single 23 l = 5 + } else { // 1/0 + 23, or noises only + l += 10 } c.ctr.XORKeyStream(b[:l], b[:l]) // caller MUST discard b if iv != nil { @@ -73,8 +73,8 @@ func (c *XorConn) Read(b []byte) (int, error) { // 5-bytes, data, 5-bytes... return len(b), nil } c.peerCtr.XORKeyStream(b, b) - if c.isHeader { - if t, _, _ := DecodeHeader(b); t == 23 { // always 5-bytes + if c.isHeader { // always 5-bytes + if t, _, _ := DecodeHeader(b); t == 23 { c.skipNext = true } else { c.isHeader = false