server.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. package encoding
  2. import (
  3. "bytes"
  4. "crypto/aes"
  5. "crypto/cipher"
  6. "crypto/md5"
  7. "crypto/sha256"
  8. "encoding/binary"
  9. "hash/fnv"
  10. "io"
  11. "sync"
  12. "time"
  13. "github.com/xtls/xray-core/common"
  14. "github.com/xtls/xray-core/common/bitmask"
  15. "github.com/xtls/xray-core/common/buf"
  16. "github.com/xtls/xray-core/common/crypto"
  17. "github.com/xtls/xray-core/common/drain"
  18. "github.com/xtls/xray-core/common/net"
  19. "github.com/xtls/xray-core/common/protocol"
  20. "github.com/xtls/xray-core/common/task"
  21. "github.com/xtls/xray-core/proxy/vmess"
  22. vmessaead "github.com/xtls/xray-core/proxy/vmess/aead"
  23. "golang.org/x/crypto/chacha20poly1305"
  24. )
  25. type sessionID struct {
  26. user [16]byte
  27. key [16]byte
  28. nonce [16]byte
  29. }
  30. // SessionHistory keeps track of historical session ids, to prevent replay attacks.
  31. type SessionHistory struct {
  32. sync.RWMutex
  33. cache map[sessionID]time.Time
  34. task *task.Periodic
  35. }
  36. // NewSessionHistory creates a new SessionHistory object.
  37. func NewSessionHistory() *SessionHistory {
  38. h := &SessionHistory{
  39. cache: make(map[sessionID]time.Time, 128),
  40. }
  41. h.task = &task.Periodic{
  42. Interval: time.Second * 30,
  43. Execute: h.removeExpiredEntries,
  44. }
  45. return h
  46. }
  47. // Close implements common.Closable.
  48. func (h *SessionHistory) Close() error {
  49. return h.task.Close()
  50. }
  51. func (h *SessionHistory) addIfNotExits(session sessionID) bool {
  52. h.Lock()
  53. if expire, found := h.cache[session]; found && expire.After(time.Now()) {
  54. h.Unlock()
  55. return false
  56. }
  57. h.cache[session] = time.Now().Add(time.Minute * 3)
  58. h.Unlock()
  59. common.Must(h.task.Start())
  60. return true
  61. }
  62. func (h *SessionHistory) removeExpiredEntries() error {
  63. now := time.Now()
  64. h.Lock()
  65. defer h.Unlock()
  66. if len(h.cache) == 0 {
  67. return newError("nothing to do")
  68. }
  69. for session, expire := range h.cache {
  70. if expire.Before(now) {
  71. delete(h.cache, session)
  72. }
  73. }
  74. if len(h.cache) == 0 {
  75. h.cache = make(map[sessionID]time.Time, 128)
  76. }
  77. return nil
  78. }
  79. // ServerSession keeps information for a session in VMess server.
  80. type ServerSession struct {
  81. userValidator *vmess.TimedUserValidator
  82. sessionHistory *SessionHistory
  83. requestBodyKey [16]byte
  84. requestBodyIV [16]byte
  85. responseBodyKey [16]byte
  86. responseBodyIV [16]byte
  87. responseWriter io.Writer
  88. responseHeader byte
  89. isAEADRequest bool
  90. isAEADForced bool
  91. }
  92. // NewServerSession creates a new ServerSession, using the given UserValidator.
  93. // The ServerSession instance doesn't take ownership of the validator.
  94. func NewServerSession(validator *vmess.TimedUserValidator, sessionHistory *SessionHistory) *ServerSession {
  95. return &ServerSession{
  96. userValidator: validator,
  97. sessionHistory: sessionHistory,
  98. }
  99. }
  100. // SetAEADForced sets isAEADForced for a ServerSession.
  101. func (s *ServerSession) SetAEADForced(isAEADForced bool) {
  102. s.isAEADForced = isAEADForced
  103. }
  104. func parseSecurityType(b byte) protocol.SecurityType {
  105. if _, f := protocol.SecurityType_name[int32(b)]; f {
  106. st := protocol.SecurityType(b)
  107. // For backward compatibility.
  108. if st == protocol.SecurityType_UNKNOWN {
  109. st = protocol.SecurityType_LEGACY
  110. }
  111. return st
  112. }
  113. return protocol.SecurityType_UNKNOWN
  114. }
  115. // DecodeRequestHeader decodes and returns (if successful) a RequestHeader from an input stream.
  116. func (s *ServerSession) DecodeRequestHeader(reader io.Reader, isDrain bool) (*protocol.RequestHeader, error) {
  117. buffer := buf.New()
  118. drainer, err := drain.NewBehaviorSeedLimitedDrainer(int64(s.userValidator.GetBehaviorSeed()), 16+38, 3266, 64)
  119. if err != nil {
  120. return nil, newError("failed to initialize drainer").Base(err)
  121. }
  122. drainConnection := func(e error) error {
  123. // We read a deterministic generated length of data before closing the connection to offset padding read pattern
  124. drainer.AcknowledgeReceive(int(buffer.Len()))
  125. if isDrain {
  126. return drain.WithError(drainer, reader, e)
  127. }
  128. return e
  129. }
  130. defer func() {
  131. buffer.Release()
  132. }()
  133. if _, err := buffer.ReadFullFrom(reader, protocol.IDBytesLen); err != nil {
  134. return nil, newError("failed to read request header").Base(err)
  135. }
  136. var decryptor io.Reader
  137. var vmessAccount *vmess.MemoryAccount
  138. user, foundAEAD, errorAEAD := s.userValidator.GetAEAD(buffer.Bytes())
  139. var fixedSizeAuthID [16]byte
  140. copy(fixedSizeAuthID[:], buffer.Bytes())
  141. switch {
  142. case foundAEAD:
  143. vmessAccount = user.Account.(*vmess.MemoryAccount)
  144. var fixedSizeCmdKey [16]byte
  145. copy(fixedSizeCmdKey[:], vmessAccount.ID.CmdKey())
  146. aeadData, shouldDrain, bytesRead, errorReason := vmessaead.OpenVMessAEADHeader(fixedSizeCmdKey, fixedSizeAuthID, reader)
  147. if errorReason != nil {
  148. if shouldDrain {
  149. drainer.AcknowledgeReceive(bytesRead)
  150. return nil, drainConnection(newError("AEAD read failed").Base(errorReason))
  151. } else {
  152. return nil, drainConnection(newError("AEAD read failed, drain skipped").Base(errorReason))
  153. }
  154. }
  155. decryptor = bytes.NewReader(aeadData)
  156. s.isAEADRequest = true
  157. case errorAEAD == vmessaead.ErrNotFound:
  158. userLegacy, timestamp, valid, userValidationError := s.userValidator.Get(buffer.Bytes())
  159. if !valid || userValidationError != nil {
  160. return nil, drainConnection(newError("invalid user").Base(userValidationError))
  161. }
  162. if s.isAEADForced {
  163. return nil, drainConnection(newError("invalid user: VMessAEAD is enforced and a non VMessAEAD connection is received. You can still disable this security feature with environment variable xray.vmess.aead.forced = false . You will not be able to enable legacy header workaround in the future."))
  164. }
  165. if s.userValidator.ShouldShowLegacyWarn() {
  166. newError("Critical Warning: potentially invalid user: a non VMessAEAD connection is received. From 2022 Jan 1st, this kind of connection will be rejected by default. You should update or replace your client software now. This message will not be shown for further violation on this inbound.").AtWarning().WriteToLog()
  167. }
  168. user = userLegacy
  169. iv := hashTimestamp(md5.New(), timestamp)
  170. vmessAccount = userLegacy.Account.(*vmess.MemoryAccount)
  171. aesStream := crypto.NewAesDecryptionStream(vmessAccount.ID.CmdKey(), iv)
  172. decryptor = crypto.NewCryptionReader(aesStream, reader)
  173. default:
  174. return nil, drainConnection(newError("invalid user").Base(errorAEAD))
  175. }
  176. drainer.AcknowledgeReceive(int(buffer.Len()))
  177. buffer.Clear()
  178. if _, err := buffer.ReadFullFrom(decryptor, 38); err != nil {
  179. return nil, newError("failed to read request header").Base(err)
  180. }
  181. request := &protocol.RequestHeader{
  182. User: user,
  183. Version: buffer.Byte(0),
  184. }
  185. copy(s.requestBodyIV[:], buffer.BytesRange(1, 17)) // 16 bytes
  186. copy(s.requestBodyKey[:], buffer.BytesRange(17, 33)) // 16 bytes
  187. var sid sessionID
  188. copy(sid.user[:], vmessAccount.ID.Bytes())
  189. sid.key = s.requestBodyKey
  190. sid.nonce = s.requestBodyIV
  191. if !s.sessionHistory.addIfNotExits(sid) {
  192. if !s.isAEADRequest {
  193. drainErr := s.userValidator.BurnTaintFuse(fixedSizeAuthID[:])
  194. if drainErr != nil {
  195. return nil, drainConnection(newError("duplicated session id, possibly under replay attack, and failed to taint userHash").Base(drainErr))
  196. }
  197. return nil, drainConnection(newError("duplicated session id, possibly under replay attack, userHash tainted"))
  198. } else {
  199. return nil, newError("duplicated session id, possibly under replay attack, but this is a AEAD request")
  200. }
  201. }
  202. s.responseHeader = buffer.Byte(33) // 1 byte
  203. request.Option = bitmask.Byte(buffer.Byte(34)) // 1 byte
  204. paddingLen := int(buffer.Byte(35) >> 4)
  205. request.Security = parseSecurityType(buffer.Byte(35) & 0x0F)
  206. // 1 bytes reserved
  207. request.Command = protocol.RequestCommand(buffer.Byte(37))
  208. switch request.Command {
  209. case protocol.RequestCommandMux:
  210. request.Address = net.DomainAddress("v1.mux.cool")
  211. request.Port = 0
  212. case protocol.RequestCommandTCP, protocol.RequestCommandUDP:
  213. if addr, port, err := addrParser.ReadAddressPort(buffer, decryptor); err == nil {
  214. request.Address = addr
  215. request.Port = port
  216. }
  217. }
  218. if paddingLen > 0 {
  219. if _, err := buffer.ReadFullFrom(decryptor, int32(paddingLen)); err != nil {
  220. if !s.isAEADRequest {
  221. burnErr := s.userValidator.BurnTaintFuse(fixedSizeAuthID[:])
  222. if burnErr != nil {
  223. return nil, newError("failed to read padding, failed to taint userHash").Base(burnErr).Base(err)
  224. }
  225. return nil, newError("failed to read padding, userHash tainted").Base(err)
  226. }
  227. return nil, newError("failed to read padding").Base(err)
  228. }
  229. }
  230. if _, err := buffer.ReadFullFrom(decryptor, 4); err != nil {
  231. if !s.isAEADRequest {
  232. burnErr := s.userValidator.BurnTaintFuse(fixedSizeAuthID[:])
  233. if burnErr != nil {
  234. return nil, newError("failed to read checksum, failed to taint userHash").Base(burnErr).Base(err)
  235. }
  236. return nil, newError("failed to read checksum, userHash tainted").Base(err)
  237. }
  238. return nil, newError("failed to read checksum").Base(err)
  239. }
  240. fnv1a := fnv.New32a()
  241. common.Must2(fnv1a.Write(buffer.BytesTo(-4)))
  242. actualHash := fnv1a.Sum32()
  243. expectedHash := binary.BigEndian.Uint32(buffer.BytesFrom(-4))
  244. if actualHash != expectedHash {
  245. if !s.isAEADRequest {
  246. Autherr := newError("invalid auth, legacy userHash tainted")
  247. burnErr := s.userValidator.BurnTaintFuse(fixedSizeAuthID[:])
  248. if burnErr != nil {
  249. Autherr = newError("invalid auth, can't taint legacy userHash").Base(burnErr)
  250. }
  251. // It is possible that we are under attack described in https://github.com/xray/xray-core/issues/2523
  252. return nil, drainConnection(Autherr)
  253. } else {
  254. return nil, newError("invalid auth, but this is a AEAD request")
  255. }
  256. }
  257. if request.Address == nil {
  258. return nil, newError("invalid remote address")
  259. }
  260. if request.Security == protocol.SecurityType_UNKNOWN || request.Security == protocol.SecurityType_AUTO {
  261. return nil, newError("unknown security type: ", request.Security)
  262. }
  263. return request, nil
  264. }
  265. // DecodeRequestBody returns Reader from which caller can fetch decrypted body.
  266. func (s *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reader io.Reader) (buf.Reader, error) {
  267. var sizeParser crypto.ChunkSizeDecoder = crypto.PlainChunkSizeParser{}
  268. if request.Option.Has(protocol.RequestOptionChunkMasking) {
  269. sizeParser = NewShakeSizeParser(s.requestBodyIV[:])
  270. }
  271. var padding crypto.PaddingLengthGenerator
  272. if request.Option.Has(protocol.RequestOptionGlobalPadding) {
  273. var ok bool
  274. padding, ok = sizeParser.(crypto.PaddingLengthGenerator)
  275. if !ok {
  276. return nil, newError("invalid option: RequestOptionGlobalPadding")
  277. }
  278. }
  279. switch request.Security {
  280. case protocol.SecurityType_NONE:
  281. if request.Option.Has(protocol.RequestOptionChunkStream) {
  282. if request.Command.TransferType() == protocol.TransferTypeStream {
  283. return crypto.NewChunkStreamReader(sizeParser, reader), nil
  284. }
  285. auth := &crypto.AEADAuthenticator{
  286. AEAD: new(NoOpAuthenticator),
  287. NonceGenerator: crypto.GenerateEmptyBytes(),
  288. AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
  289. }
  290. return crypto.NewAuthenticationReader(auth, sizeParser, reader, protocol.TransferTypePacket, padding), nil
  291. }
  292. return buf.NewReader(reader), nil
  293. case protocol.SecurityType_LEGACY:
  294. aesStream := crypto.NewAesDecryptionStream(s.requestBodyKey[:], s.requestBodyIV[:])
  295. cryptionReader := crypto.NewCryptionReader(aesStream, reader)
  296. if request.Option.Has(protocol.RequestOptionChunkStream) {
  297. auth := &crypto.AEADAuthenticator{
  298. AEAD: new(FnvAuthenticator),
  299. NonceGenerator: crypto.GenerateEmptyBytes(),
  300. AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
  301. }
  302. return crypto.NewAuthenticationReader(auth, sizeParser, cryptionReader, request.Command.TransferType(), padding), nil
  303. }
  304. return buf.NewReader(cryptionReader), nil
  305. case protocol.SecurityType_AES128_GCM:
  306. aead := crypto.NewAesGcm(s.requestBodyKey[:])
  307. auth := &crypto.AEADAuthenticator{
  308. AEAD: aead,
  309. NonceGenerator: GenerateChunkNonce(s.requestBodyIV[:], uint32(aead.NonceSize())),
  310. AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
  311. }
  312. if request.Option.Has(protocol.RequestOptionAuthenticatedLength) {
  313. AuthenticatedLengthKey := vmessaead.KDF16(s.requestBodyKey[:], "auth_len")
  314. AuthenticatedLengthKeyAEAD := crypto.NewAesGcm(AuthenticatedLengthKey)
  315. lengthAuth := &crypto.AEADAuthenticator{
  316. AEAD: AuthenticatedLengthKeyAEAD,
  317. NonceGenerator: GenerateChunkNonce(s.requestBodyIV[:], uint32(aead.NonceSize())),
  318. AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
  319. }
  320. sizeParser = NewAEADSizeParser(lengthAuth)
  321. }
  322. return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType(), padding), nil
  323. case protocol.SecurityType_CHACHA20_POLY1305:
  324. aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(s.requestBodyKey[:]))
  325. auth := &crypto.AEADAuthenticator{
  326. AEAD: aead,
  327. NonceGenerator: GenerateChunkNonce(s.requestBodyIV[:], uint32(aead.NonceSize())),
  328. AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
  329. }
  330. if request.Option.Has(protocol.RequestOptionAuthenticatedLength) {
  331. AuthenticatedLengthKey := vmessaead.KDF16(s.requestBodyKey[:], "auth_len")
  332. AuthenticatedLengthKeyAEAD, err := chacha20poly1305.New(GenerateChacha20Poly1305Key(AuthenticatedLengthKey))
  333. common.Must(err)
  334. lengthAuth := &crypto.AEADAuthenticator{
  335. AEAD: AuthenticatedLengthKeyAEAD,
  336. NonceGenerator: GenerateChunkNonce(s.requestBodyIV[:], uint32(aead.NonceSize())),
  337. AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
  338. }
  339. sizeParser = NewAEADSizeParser(lengthAuth)
  340. }
  341. return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType(), padding), nil
  342. default:
  343. return nil, newError("invalid option: Security")
  344. }
  345. }
  346. // EncodeResponseHeader writes encoded response header into the given writer.
  347. func (s *ServerSession) EncodeResponseHeader(header *protocol.ResponseHeader, writer io.Writer) {
  348. var encryptionWriter io.Writer
  349. if !s.isAEADRequest {
  350. s.responseBodyKey = md5.Sum(s.requestBodyKey[:])
  351. s.responseBodyIV = md5.Sum(s.requestBodyIV[:])
  352. } else {
  353. BodyKey := sha256.Sum256(s.requestBodyKey[:])
  354. copy(s.responseBodyKey[:], BodyKey[:16])
  355. BodyIV := sha256.Sum256(s.requestBodyIV[:])
  356. copy(s.responseBodyIV[:], BodyIV[:16])
  357. }
  358. aesStream := crypto.NewAesEncryptionStream(s.responseBodyKey[:], s.responseBodyIV[:])
  359. encryptionWriter = crypto.NewCryptionWriter(aesStream, writer)
  360. s.responseWriter = encryptionWriter
  361. aeadEncryptedHeaderBuffer := bytes.NewBuffer(nil)
  362. if s.isAEADRequest {
  363. encryptionWriter = aeadEncryptedHeaderBuffer
  364. }
  365. common.Must2(encryptionWriter.Write([]byte{s.responseHeader, byte(header.Option)}))
  366. err := MarshalCommand(header.Command, encryptionWriter)
  367. if err != nil {
  368. common.Must2(encryptionWriter.Write([]byte{0x00, 0x00}))
  369. }
  370. if s.isAEADRequest {
  371. aeadResponseHeaderLengthEncryptionKey := vmessaead.KDF16(s.responseBodyKey[:], vmessaead.KDFSaltConstAEADRespHeaderLenKey)
  372. aeadResponseHeaderLengthEncryptionIV := vmessaead.KDF(s.responseBodyIV[:], vmessaead.KDFSaltConstAEADRespHeaderLenIV)[:12]
  373. aeadResponseHeaderLengthEncryptionKeyAESBlock := common.Must2(aes.NewCipher(aeadResponseHeaderLengthEncryptionKey)).(cipher.Block)
  374. aeadResponseHeaderLengthEncryptionAEAD := common.Must2(cipher.NewGCM(aeadResponseHeaderLengthEncryptionKeyAESBlock)).(cipher.AEAD)
  375. aeadResponseHeaderLengthEncryptionBuffer := bytes.NewBuffer(nil)
  376. decryptedResponseHeaderLengthBinaryDeserializeBuffer := uint16(aeadEncryptedHeaderBuffer.Len())
  377. common.Must(binary.Write(aeadResponseHeaderLengthEncryptionBuffer, binary.BigEndian, decryptedResponseHeaderLengthBinaryDeserializeBuffer))
  378. AEADEncryptedLength := aeadResponseHeaderLengthEncryptionAEAD.Seal(nil, aeadResponseHeaderLengthEncryptionIV, aeadResponseHeaderLengthEncryptionBuffer.Bytes(), nil)
  379. common.Must2(io.Copy(writer, bytes.NewReader(AEADEncryptedLength)))
  380. aeadResponseHeaderPayloadEncryptionKey := vmessaead.KDF16(s.responseBodyKey[:], vmessaead.KDFSaltConstAEADRespHeaderPayloadKey)
  381. aeadResponseHeaderPayloadEncryptionIV := vmessaead.KDF(s.responseBodyIV[:], vmessaead.KDFSaltConstAEADRespHeaderPayloadIV)[:12]
  382. aeadResponseHeaderPayloadEncryptionKeyAESBlock := common.Must2(aes.NewCipher(aeadResponseHeaderPayloadEncryptionKey)).(cipher.Block)
  383. aeadResponseHeaderPayloadEncryptionAEAD := common.Must2(cipher.NewGCM(aeadResponseHeaderPayloadEncryptionKeyAESBlock)).(cipher.AEAD)
  384. aeadEncryptedHeaderPayload := aeadResponseHeaderPayloadEncryptionAEAD.Seal(nil, aeadResponseHeaderPayloadEncryptionIV, aeadEncryptedHeaderBuffer.Bytes(), nil)
  385. common.Must2(io.Copy(writer, bytes.NewReader(aeadEncryptedHeaderPayload)))
  386. }
  387. }
  388. // EncodeResponseBody returns a Writer that auto-encrypt content written by caller.
  389. func (s *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writer io.Writer) (buf.Writer, error) {
  390. var sizeParser crypto.ChunkSizeEncoder = crypto.PlainChunkSizeParser{}
  391. if request.Option.Has(protocol.RequestOptionChunkMasking) {
  392. sizeParser = NewShakeSizeParser(s.responseBodyIV[:])
  393. }
  394. var padding crypto.PaddingLengthGenerator
  395. if request.Option.Has(protocol.RequestOptionGlobalPadding) {
  396. var ok bool
  397. padding, ok = sizeParser.(crypto.PaddingLengthGenerator)
  398. if !ok {
  399. return nil, newError("invalid option: RequestOptionGlobalPadding")
  400. }
  401. }
  402. switch request.Security {
  403. case protocol.SecurityType_NONE:
  404. if request.Option.Has(protocol.RequestOptionChunkStream) {
  405. if request.Command.TransferType() == protocol.TransferTypeStream {
  406. return crypto.NewChunkStreamWriter(sizeParser, writer), nil
  407. }
  408. auth := &crypto.AEADAuthenticator{
  409. AEAD: new(NoOpAuthenticator),
  410. NonceGenerator: crypto.GenerateEmptyBytes(),
  411. AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
  412. }
  413. return crypto.NewAuthenticationWriter(auth, sizeParser, writer, protocol.TransferTypePacket, padding), nil
  414. }
  415. return buf.NewWriter(writer), nil
  416. case protocol.SecurityType_LEGACY:
  417. if request.Option.Has(protocol.RequestOptionChunkStream) {
  418. auth := &crypto.AEADAuthenticator{
  419. AEAD: new(FnvAuthenticator),
  420. NonceGenerator: crypto.GenerateEmptyBytes(),
  421. AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
  422. }
  423. return crypto.NewAuthenticationWriter(auth, sizeParser, s.responseWriter, request.Command.TransferType(), padding), nil
  424. }
  425. return &buf.SequentialWriter{Writer: s.responseWriter}, nil
  426. case protocol.SecurityType_AES128_GCM:
  427. aead := crypto.NewAesGcm(s.responseBodyKey[:])
  428. auth := &crypto.AEADAuthenticator{
  429. AEAD: aead,
  430. NonceGenerator: GenerateChunkNonce(s.responseBodyIV[:], uint32(aead.NonceSize())),
  431. AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
  432. }
  433. if request.Option.Has(protocol.RequestOptionAuthenticatedLength) {
  434. AuthenticatedLengthKey := vmessaead.KDF16(s.requestBodyKey[:], "auth_len")
  435. AuthenticatedLengthKeyAEAD := crypto.NewAesGcm(AuthenticatedLengthKey)
  436. lengthAuth := &crypto.AEADAuthenticator{
  437. AEAD: AuthenticatedLengthKeyAEAD,
  438. NonceGenerator: GenerateChunkNonce(s.requestBodyIV[:], uint32(aead.NonceSize())),
  439. AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
  440. }
  441. sizeParser = NewAEADSizeParser(lengthAuth)
  442. }
  443. return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType(), padding), nil
  444. case protocol.SecurityType_CHACHA20_POLY1305:
  445. aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(s.responseBodyKey[:]))
  446. auth := &crypto.AEADAuthenticator{
  447. AEAD: aead,
  448. NonceGenerator: GenerateChunkNonce(s.responseBodyIV[:], uint32(aead.NonceSize())),
  449. AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
  450. }
  451. if request.Option.Has(protocol.RequestOptionAuthenticatedLength) {
  452. AuthenticatedLengthKey := vmessaead.KDF16(s.requestBodyKey[:], "auth_len")
  453. AuthenticatedLengthKeyAEAD, err := chacha20poly1305.New(GenerateChacha20Poly1305Key(AuthenticatedLengthKey))
  454. common.Must(err)
  455. lengthAuth := &crypto.AEADAuthenticator{
  456. AEAD: AuthenticatedLengthKeyAEAD,
  457. NonceGenerator: GenerateChunkNonce(s.requestBodyIV[:], uint32(aead.NonceSize())),
  458. AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
  459. }
  460. sizeParser = NewAEADSizeParser(lengthAuth)
  461. }
  462. return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType(), padding), nil
  463. default:
  464. return nil, newError("invalid option: Security")
  465. }
  466. }