diff --git a/proxy/vless/encryption/client.go b/proxy/vless/encryption/client.go index 1ea2ecc5..9a17135e 100644 --- a/proxy/vless/encryption/client.go +++ b/proxy/vless/encryption/client.go @@ -104,9 +104,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 } @@ -190,9 +190,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/proxy/vless/encryption/common.go b/proxy/vless/encryption/common.go index 7f879dc1..58c096e3 100644 --- a/proxy/vless/encryption/common.go +++ b/proxy/vless/encryption/common.go @@ -47,7 +47,7 @@ func DecodeHeader(h []byte) (t byte, l int, err error) { l = 0 } if l < 17 || l > 17000 { // TODO: TLSv1.3 max length - err = errors.New("invalid header: ", fmt.Sprintf("%v", h[:5])) // relied by client's Read() + err = errors.New("invalid header: ", fmt.Sprintf("%v", h[:5])) // DO NOT CHANGE: relied by client's Read() } return } diff --git a/proxy/vless/encryption/server.go b/proxy/vless/encryption/server.go index 72346575..c5b0163e 100644 --- a/proxy/vless/encryption/server.go +++ b/proxy/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, crypto.RandBetween(100, 1000)) - rand.Read(noise) - c.Conn.Write(noise) // make client do new handshake + noises := make([]byte, crypto.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/proxy/vless/encryption/xor.go b/proxy/vless/encryption/xor.go index bbe489ef..64828eaa 100644 --- a/proxy/vless/encryption/xor.go +++ b/proxy/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