1
0

client.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. package encryption
  2. import (
  3. "crypto/cipher"
  4. "crypto/ecdh"
  5. "crypto/mlkem"
  6. "crypto/rand"
  7. "io"
  8. "net"
  9. "sync"
  10. "time"
  11. "github.com/xtls/xray-core/common/errors"
  12. "github.com/xtls/xray-core/common/protocol"
  13. "lukechampine.com/blake3"
  14. )
  15. type ClientInstance struct {
  16. NfsPKeys []any
  17. NfsPKeysBytes [][]byte
  18. Hash32s [][32]byte
  19. RelaysLength int
  20. XorMode uint32
  21. Seconds uint32
  22. PaddingLens [][3]int
  23. PaddingGaps [][3]int
  24. RWLock sync.RWMutex
  25. Expire time.Time
  26. PfsKey []byte
  27. Ticket []byte
  28. }
  29. func (i *ClientInstance) Init(nfsPKeysBytes [][]byte, xorMode, seconds uint32, padding string) (err error) {
  30. if i.NfsPKeys != nil {
  31. return errors.New("already initialized")
  32. }
  33. l := len(nfsPKeysBytes)
  34. if l == 0 {
  35. return errors.New("empty nfsPKeysBytes")
  36. }
  37. i.NfsPKeys = make([]any, l)
  38. i.NfsPKeysBytes = nfsPKeysBytes
  39. i.Hash32s = make([][32]byte, l)
  40. for j, k := range nfsPKeysBytes {
  41. if len(k) == 32 {
  42. if i.NfsPKeys[j], err = ecdh.X25519().NewPublicKey(k); err != nil {
  43. return
  44. }
  45. i.RelaysLength += 32 + 32
  46. } else {
  47. if i.NfsPKeys[j], err = mlkem.NewEncapsulationKey768(k); err != nil {
  48. return
  49. }
  50. i.RelaysLength += 1088 + 32
  51. }
  52. i.Hash32s[j] = blake3.Sum256(k)
  53. }
  54. i.RelaysLength -= 32
  55. i.XorMode = xorMode
  56. i.Seconds = seconds
  57. return ParsePadding(padding, &i.PaddingLens, &i.PaddingGaps)
  58. }
  59. func (i *ClientInstance) Handshake(conn net.Conn) (*CommonConn, error) {
  60. if i.NfsPKeys == nil {
  61. return nil, errors.New("uninitialized")
  62. }
  63. c := NewCommonConn(conn, protocol.HasAESGCMHardwareSupport)
  64. ivAndRealysLength := 16 + i.RelaysLength
  65. pfsKeyExchangeLength := 18 + 1184 + 32 + 16
  66. paddingLength, paddingLens, paddingGaps := CreatPadding(i.PaddingLens, i.PaddingGaps)
  67. clientHello := make([]byte, ivAndRealysLength+pfsKeyExchangeLength+paddingLength)
  68. iv := clientHello[:16]
  69. rand.Read(iv)
  70. relays := clientHello[16:ivAndRealysLength]
  71. var nfsKey []byte
  72. var lastCTR cipher.Stream
  73. for j, k := range i.NfsPKeys {
  74. var index = 32
  75. if k, ok := k.(*ecdh.PublicKey); ok {
  76. privateKey, _ := ecdh.X25519().GenerateKey(rand.Reader)
  77. copy(relays, privateKey.PublicKey().Bytes())
  78. var err error
  79. nfsKey, err = privateKey.ECDH(k)
  80. if err != nil {
  81. return nil, err
  82. }
  83. }
  84. if k, ok := k.(*mlkem.EncapsulationKey768); ok {
  85. var ciphertext []byte
  86. nfsKey, ciphertext = k.Encapsulate()
  87. copy(relays, ciphertext)
  88. index = 1088
  89. }
  90. if i.XorMode > 0 { // this xor can (others can't) be recovered by client's config, revealing an X25519 public key / ML-KEM-768 ciphertext, that's why "native" values
  91. NewCTR(i.NfsPKeysBytes[j], iv).XORKeyStream(relays, relays[:index]) // make X25519 public key / ML-KEM-768 ciphertext distinguishable from random bytes
  92. }
  93. if lastCTR != nil {
  94. lastCTR.XORKeyStream(relays, relays[:32]) // make this relay irreplaceable
  95. }
  96. if j == len(i.NfsPKeys)-1 {
  97. break
  98. }
  99. lastCTR = NewCTR(nfsKey, iv)
  100. lastCTR.XORKeyStream(relays[index:], i.Hash32s[j+1][:])
  101. relays = relays[index+32:]
  102. }
  103. nfsAEAD := NewAEAD(iv, nfsKey, c.UseAES)
  104. if i.Seconds > 0 {
  105. i.RWLock.RLock()
  106. if time.Now().Before(i.Expire) {
  107. c.Client = i
  108. c.UnitedKey = append(i.PfsKey, nfsKey...) // different unitedKey for each connection
  109. nfsAEAD.Seal(clientHello[:ivAndRealysLength], nil, EncodeLength(32), nil)
  110. nfsAEAD.Seal(clientHello[:ivAndRealysLength+18], nil, i.Ticket, nil)
  111. i.RWLock.RUnlock()
  112. c.PreWrite = clientHello[:ivAndRealysLength+18+32]
  113. c.AEAD = NewAEAD(clientHello[ivAndRealysLength+18:ivAndRealysLength+18+32], c.UnitedKey, c.UseAES)
  114. if i.XorMode == 2 {
  115. c.Conn = NewXorConn(conn, NewCTR(c.UnitedKey, iv), nil, len(c.PreWrite), 16)
  116. }
  117. return c, nil
  118. }
  119. i.RWLock.RUnlock()
  120. }
  121. pfsKeyExchange := clientHello[ivAndRealysLength : ivAndRealysLength+pfsKeyExchangeLength]
  122. nfsAEAD.Seal(pfsKeyExchange[:0], nil, EncodeLength(pfsKeyExchangeLength-18), nil)
  123. mlkem768DKey, _ := mlkem.GenerateKey768()
  124. x25519SKey, _ := ecdh.X25519().GenerateKey(rand.Reader)
  125. pfsPublicKey := append(mlkem768DKey.EncapsulationKey().Bytes(), x25519SKey.PublicKey().Bytes()...)
  126. nfsAEAD.Seal(pfsKeyExchange[:18], nil, pfsPublicKey, nil)
  127. padding := clientHello[ivAndRealysLength+pfsKeyExchangeLength:]
  128. nfsAEAD.Seal(padding[:0], nil, EncodeLength(paddingLength-18), nil)
  129. nfsAEAD.Seal(padding[:18], nil, padding[18:paddingLength-16], nil)
  130. paddingLens[0] = ivAndRealysLength + pfsKeyExchangeLength + paddingLens[0]
  131. for i, l := range paddingLens { // sends padding in a fragmented way, to create variable traffic pattern, before inner VLESS flow takes control
  132. if l > 0 {
  133. if _, err := conn.Write(clientHello[:l]); err != nil {
  134. return nil, err
  135. }
  136. clientHello = clientHello[l:]
  137. }
  138. if len(paddingGaps) > i {
  139. time.Sleep(paddingGaps[i])
  140. }
  141. }
  142. encryptedPfsPublicKey := make([]byte, 1088+32+16)
  143. if _, err := io.ReadFull(conn, encryptedPfsPublicKey); err != nil {
  144. return nil, err
  145. }
  146. nfsAEAD.Open(encryptedPfsPublicKey[:0], MaxNonce, encryptedPfsPublicKey, nil)
  147. mlkem768Key, err := mlkem768DKey.Decapsulate(encryptedPfsPublicKey[:1088])
  148. if err != nil {
  149. return nil, err
  150. }
  151. peerX25519PKey, err := ecdh.X25519().NewPublicKey(encryptedPfsPublicKey[1088 : 1088+32])
  152. if err != nil {
  153. return nil, err
  154. }
  155. x25519Key, err := x25519SKey.ECDH(peerX25519PKey)
  156. if err != nil {
  157. return nil, err
  158. }
  159. pfsKey := make([]byte, 32+32) // no more capacity
  160. copy(pfsKey, mlkem768Key)
  161. copy(pfsKey[32:], x25519Key)
  162. c.UnitedKey = append(pfsKey, nfsKey...)
  163. c.AEAD = NewAEAD(pfsPublicKey, c.UnitedKey, c.UseAES)
  164. c.PeerAEAD = NewAEAD(encryptedPfsPublicKey[:1088+32], c.UnitedKey, c.UseAES)
  165. encryptedTicket := make([]byte, 32)
  166. if _, err := io.ReadFull(conn, encryptedTicket); err != nil {
  167. return nil, err
  168. }
  169. if _, err := c.PeerAEAD.Open(encryptedTicket[:0], nil, encryptedTicket, nil); err != nil {
  170. return nil, err
  171. }
  172. seconds := DecodeLength(encryptedTicket)
  173. if i.Seconds > 0 && seconds > 0 {
  174. i.RWLock.Lock()
  175. i.Expire = time.Now().Add(time.Duration(seconds) * time.Second)
  176. i.PfsKey = pfsKey
  177. i.Ticket = encryptedTicket[:16]
  178. i.RWLock.Unlock()
  179. }
  180. encryptedLength := make([]byte, 18)
  181. if _, err := io.ReadFull(conn, encryptedLength); err != nil {
  182. return nil, err
  183. }
  184. if _, err := c.PeerAEAD.Open(encryptedLength[:0], nil, encryptedLength, nil); err != nil {
  185. return nil, err
  186. }
  187. length := DecodeLength(encryptedLength[:2])
  188. c.PeerPadding = make([]byte, length) // important: allows server sends padding slowly, eliminating 1-RTT's traffic pattern
  189. if i.XorMode == 2 {
  190. c.Conn = NewXorConn(conn, NewCTR(c.UnitedKey, iv), NewCTR(c.UnitedKey, encryptedTicket[:16]), 0, length)
  191. }
  192. return c, nil
  193. }