server.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. package encryption
  2. import (
  3. "bytes"
  4. "crypto/cipher"
  5. "crypto/ecdh"
  6. "crypto/mlkem"
  7. "crypto/rand"
  8. "fmt"
  9. "io"
  10. "net"
  11. "sync"
  12. "time"
  13. "github.com/xtls/xray-core/common/crypto"
  14. "github.com/xtls/xray-core/common/errors"
  15. "lukechampine.com/blake3"
  16. )
  17. type ServerSession struct {
  18. Expire time.Time
  19. PfsKey []byte
  20. NfsKeys sync.Map
  21. }
  22. type ServerInstance struct {
  23. NfsSKeys []any
  24. NfsPKeysBytes [][]byte
  25. Hash32s [][32]byte
  26. RelaysLength int
  27. XorMode uint32
  28. Seconds uint32
  29. PaddingLens [][3]int
  30. PaddingGaps [][3]int
  31. RWLock sync.RWMutex
  32. Sessions map[[16]byte]*ServerSession
  33. Closed bool
  34. }
  35. func (i *ServerInstance) Init(nfsSKeysBytes [][]byte, xorMode, seconds uint32, padding string) (err error) {
  36. if i.NfsSKeys != nil {
  37. return errors.New("already initialized")
  38. }
  39. l := len(nfsSKeysBytes)
  40. if l == 0 {
  41. return errors.New("empty nfsSKeysBytes")
  42. }
  43. i.NfsSKeys = make([]any, l)
  44. i.NfsPKeysBytes = make([][]byte, l)
  45. i.Hash32s = make([][32]byte, l)
  46. for j, k := range nfsSKeysBytes {
  47. if len(k) == 32 {
  48. if i.NfsSKeys[j], err = ecdh.X25519().NewPrivateKey(k); err != nil {
  49. return
  50. }
  51. i.NfsPKeysBytes[j] = i.NfsSKeys[j].(*ecdh.PrivateKey).PublicKey().Bytes()
  52. i.RelaysLength += 32 + 32
  53. } else {
  54. if i.NfsSKeys[j], err = mlkem.NewDecapsulationKey768(k); err != nil {
  55. return
  56. }
  57. i.NfsPKeysBytes[j] = i.NfsSKeys[j].(*mlkem.DecapsulationKey768).EncapsulationKey().Bytes()
  58. i.RelaysLength += 1088 + 32
  59. }
  60. i.Hash32s[j] = blake3.Sum256(i.NfsPKeysBytes[j])
  61. }
  62. i.RelaysLength -= 32
  63. i.XorMode = xorMode
  64. if seconds > 0 {
  65. i.Seconds = seconds
  66. i.Sessions = make(map[[16]byte]*ServerSession)
  67. go func() {
  68. for {
  69. time.Sleep(time.Minute)
  70. i.RWLock.Lock()
  71. if i.Closed {
  72. i.RWLock.Unlock()
  73. return
  74. }
  75. now := time.Now()
  76. for ticket, session := range i.Sessions {
  77. if now.After(session.Expire) {
  78. delete(i.Sessions, ticket)
  79. }
  80. }
  81. i.RWLock.Unlock()
  82. }
  83. }()
  84. }
  85. return ParsePadding(padding, &i.PaddingLens, &i.PaddingGaps)
  86. }
  87. func (i *ServerInstance) Close() (err error) {
  88. i.RWLock.Lock()
  89. i.Closed = true
  90. i.RWLock.Unlock()
  91. return
  92. }
  93. func (i *ServerInstance) Handshake(conn net.Conn, fallback *[]byte) (*CommonConn, error) {
  94. if i.NfsSKeys == nil {
  95. return nil, errors.New("uninitialized")
  96. }
  97. c := NewCommonConn(conn, true)
  98. ivAndRelays := make([]byte, 16+i.RelaysLength)
  99. if _, err := io.ReadFull(conn, ivAndRelays); err != nil {
  100. return nil, err
  101. }
  102. if fallback != nil {
  103. *fallback = append(*fallback, ivAndRelays...)
  104. }
  105. iv := ivAndRelays[:16]
  106. relays := ivAndRelays[16:]
  107. var nfsKey []byte
  108. var lastCTR cipher.Stream
  109. for j, k := range i.NfsSKeys {
  110. if lastCTR != nil {
  111. lastCTR.XORKeyStream(relays, relays[:32]) // recover this relay
  112. }
  113. var index = 32
  114. if _, ok := k.(*mlkem.DecapsulationKey768); ok {
  115. index = 1088
  116. }
  117. if i.XorMode > 0 {
  118. NewCTR(i.NfsPKeysBytes[j], iv).XORKeyStream(relays, relays[:index]) // we don't use buggy elligator, because we have PSK :)
  119. }
  120. if k, ok := k.(*ecdh.PrivateKey); ok {
  121. publicKey, err := ecdh.X25519().NewPublicKey(relays[:index])
  122. if err != nil {
  123. return nil, err
  124. }
  125. nfsKey, err = k.ECDH(publicKey)
  126. if err != nil {
  127. return nil, err
  128. }
  129. }
  130. if k, ok := k.(*mlkem.DecapsulationKey768); ok {
  131. var err error
  132. nfsKey, err = k.Decapsulate(relays[:index])
  133. if err != nil {
  134. return nil, err
  135. }
  136. }
  137. if j == len(i.NfsSKeys)-1 {
  138. break
  139. }
  140. relays = relays[index:]
  141. lastCTR = NewCTR(nfsKey, iv)
  142. lastCTR.XORKeyStream(relays, relays[:32])
  143. if !bytes.Equal(relays[:32], i.Hash32s[j+1][:]) {
  144. return nil, errors.New("unexpected hash32: ", fmt.Sprintf("%v", relays[:32]))
  145. }
  146. relays = relays[32:]
  147. }
  148. nfsAEAD := NewAEAD(iv, nfsKey, c.UseAES)
  149. encryptedLength := make([]byte, 18)
  150. if _, err := io.ReadFull(conn, encryptedLength); err != nil {
  151. return nil, err
  152. }
  153. if fallback != nil {
  154. *fallback = append(*fallback, encryptedLength...)
  155. }
  156. decryptedLength := make([]byte, 2)
  157. if _, err := nfsAEAD.Open(decryptedLength[:0], nil, encryptedLength, nil); err != nil {
  158. c.UseAES = !c.UseAES
  159. nfsAEAD = NewAEAD(iv, nfsKey, c.UseAES)
  160. if _, err := nfsAEAD.Open(decryptedLength[:0], nil, encryptedLength, nil); err != nil {
  161. return nil, err
  162. }
  163. }
  164. if fallback != nil {
  165. *fallback = nil
  166. }
  167. length := DecodeLength(decryptedLength)
  168. if length == 32 {
  169. if i.Seconds == 0 {
  170. return nil, errors.New("0-RTT is not allowed")
  171. }
  172. encryptedTicket := make([]byte, 32)
  173. if _, err := io.ReadFull(conn, encryptedTicket); err != nil {
  174. return nil, err
  175. }
  176. ticket, err := nfsAEAD.Open(nil, nil, encryptedTicket, nil)
  177. if err != nil {
  178. return nil, err
  179. }
  180. i.RWLock.RLock()
  181. s := i.Sessions[[16]byte(ticket)]
  182. i.RWLock.RUnlock()
  183. if s == nil {
  184. noises := make([]byte, crypto.RandBetween(1279, 2279)) // matches 1-RTT's server hello length for "random", though it is not important, just for example
  185. var err error
  186. for err == nil {
  187. rand.Read(noises)
  188. _, err = DecodeHeader(noises)
  189. }
  190. conn.Write(noises) // make client do new handshake
  191. return nil, errors.New("expired ticket")
  192. }
  193. if _, loaded := s.NfsKeys.LoadOrStore([32]byte(nfsKey), true); loaded { // prevents bad client also
  194. return nil, errors.New("replay detected")
  195. }
  196. c.UnitedKey = append(s.PfsKey, nfsKey...) // the same nfsKey links the upload & download (prevents server -> client's another request)
  197. c.PreWrite = make([]byte, 16)
  198. rand.Read(c.PreWrite) // always trust yourself, not the client (also prevents being parsed as TLS thus causing false interruption for "native" and "xorpub")
  199. c.AEAD = NewAEAD(c.PreWrite, c.UnitedKey, c.UseAES)
  200. c.PeerAEAD = NewAEAD(encryptedTicket, c.UnitedKey, c.UseAES) // unchangeable ctx (prevents server -> server), and different ctx length for upload / download (prevents client -> client)
  201. if i.XorMode == 2 {
  202. c.Conn = NewXorConn(conn, NewCTR(c.UnitedKey, c.PreWrite), NewCTR(c.UnitedKey, iv), 16, 0) // it doesn't matter if the attacker sends client's iv back to the client
  203. }
  204. return c, nil
  205. }
  206. if length < 1184+32+16 { // client may send more public keys in the future's version
  207. return nil, errors.New("too short length")
  208. }
  209. encryptedPfsPublicKey := make([]byte, length)
  210. if _, err := io.ReadFull(conn, encryptedPfsPublicKey); err != nil {
  211. return nil, err
  212. }
  213. if _, err := nfsAEAD.Open(encryptedPfsPublicKey[:0], nil, encryptedPfsPublicKey, nil); err != nil {
  214. return nil, err
  215. }
  216. mlkem768EKey, err := mlkem.NewEncapsulationKey768(encryptedPfsPublicKey[:1184])
  217. if err != nil {
  218. return nil, err
  219. }
  220. mlkem768Key, encapsulatedPfsKey := mlkem768EKey.Encapsulate()
  221. peerX25519PKey, err := ecdh.X25519().NewPublicKey(encryptedPfsPublicKey[1184 : 1184+32])
  222. if err != nil {
  223. return nil, err
  224. }
  225. x25519SKey, _ := ecdh.X25519().GenerateKey(rand.Reader)
  226. x25519Key, err := x25519SKey.ECDH(peerX25519PKey)
  227. if err != nil {
  228. return nil, err
  229. }
  230. pfsKey := make([]byte, 32+32) // no more capacity
  231. copy(pfsKey, mlkem768Key)
  232. copy(pfsKey[32:], x25519Key)
  233. pfsPublicKey := append(encapsulatedPfsKey, x25519SKey.PublicKey().Bytes()...)
  234. c.UnitedKey = append(pfsKey, nfsKey...)
  235. c.AEAD = NewAEAD(pfsPublicKey, c.UnitedKey, c.UseAES)
  236. c.PeerAEAD = NewAEAD(encryptedPfsPublicKey[:1184+32], c.UnitedKey, c.UseAES)
  237. ticket := make([]byte, 16)
  238. rand.Read(ticket)
  239. copy(ticket, EncodeLength(int(i.Seconds*4/5)))
  240. if i.Seconds > 0 {
  241. i.RWLock.Lock()
  242. i.Sessions[[16]byte(ticket)] = &ServerSession{
  243. Expire: time.Now().Add(time.Duration(i.Seconds) * time.Second),
  244. PfsKey: pfsKey,
  245. }
  246. i.RWLock.Unlock()
  247. }
  248. pfsKeyExchangeLength := 1088 + 32 + 16
  249. encryptedTicketLength := 32
  250. paddingLength, paddingLens, paddingGaps := CreatPadding(i.PaddingLens, i.PaddingGaps)
  251. serverHello := make([]byte, pfsKeyExchangeLength+encryptedTicketLength+paddingLength)
  252. nfsAEAD.Seal(serverHello[:0], MaxNonce, pfsPublicKey, nil)
  253. c.AEAD.Seal(serverHello[:pfsKeyExchangeLength], nil, ticket, nil)
  254. padding := serverHello[pfsKeyExchangeLength+encryptedTicketLength:]
  255. c.AEAD.Seal(padding[:0], nil, EncodeLength(paddingLength-18), nil)
  256. c.AEAD.Seal(padding[:18], nil, padding[18:paddingLength-16], nil)
  257. paddingLens[0] = pfsKeyExchangeLength + encryptedTicketLength + paddingLens[0]
  258. for i, l := range paddingLens { // sends padding in a fragmented way, to create variable traffic pattern, before inner VLESS flow takes control
  259. if l > 0 {
  260. if _, err := conn.Write(serverHello[:l]); err != nil {
  261. return nil, err
  262. }
  263. serverHello = serverHello[l:]
  264. }
  265. if len(paddingGaps) > i {
  266. time.Sleep(paddingGaps[i])
  267. }
  268. }
  269. // important: allows client sends padding slowly, eliminating 1-RTT's traffic pattern
  270. if _, err := io.ReadFull(conn, encryptedLength); err != nil {
  271. return nil, err
  272. }
  273. if _, err := nfsAEAD.Open(encryptedLength[:0], nil, encryptedLength, nil); err != nil {
  274. return nil, err
  275. }
  276. encryptedPadding := make([]byte, DecodeLength(encryptedLength[:2]))
  277. if _, err := io.ReadFull(conn, encryptedPadding); err != nil {
  278. return nil, err
  279. }
  280. if _, err := nfsAEAD.Open(encryptedPadding[:0], nil, encryptedPadding, nil); err != nil {
  281. return nil, err
  282. }
  283. if i.XorMode == 2 {
  284. c.Conn = NewXorConn(conn, NewCTR(c.UnitedKey, ticket), NewCTR(c.UnitedKey, iv), 0, 0)
  285. }
  286. return c, nil
  287. }