encoding.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. package shadowsocks2022
  2. import (
  3. "bytes"
  4. "crypto/cipher"
  5. cryptoRand "crypto/rand"
  6. "io"
  7. "math/rand"
  8. "time"
  9. "github.com/lunixbochs/struc"
  10. "github.com/v2fly/v2ray-core/v5/common/buf"
  11. "github.com/v2fly/v2ray-core/v5/common/crypto"
  12. "github.com/v2fly/v2ray-core/v5/common/net"
  13. "github.com/v2fly/v2ray-core/v5/common/protocol"
  14. )
  15. type TCPRequest struct {
  16. keyDerivation KeyDerivation
  17. method Method
  18. c2sSalt RequestSalt
  19. c2sNonce crypto.BytesGenerator
  20. c2sAEAD cipher.AEAD
  21. s2cSalt RequestSalt
  22. s2cNonce crypto.BytesGenerator
  23. s2cAEAD cipher.AEAD
  24. s2cSaltAssert RequestSalt
  25. s2cInitialPayloadSize int
  26. }
  27. func (t *TCPRequest) EncodeTCPRequestHeader(effectivePsk []byte,
  28. eih [][]byte, address DestinationAddress, destPort int, initialPayload []byte, out *buf.Buffer,
  29. ) error {
  30. requestSalt := newRequestSaltWithLength(t.method.GetSessionSubKeyAndSaltLength())
  31. {
  32. err := requestSalt.FillAllFrom(cryptoRand.Reader)
  33. if err != nil {
  34. return newError("failed to fill salt").Base(err)
  35. }
  36. }
  37. t.c2sSalt = requestSalt
  38. sessionKey := make([]byte, t.method.GetSessionSubKeyAndSaltLength())
  39. {
  40. err := t.keyDerivation.GetSessionSubKey(effectivePsk, requestSalt.Bytes(), sessionKey)
  41. if err != nil {
  42. return newError("failed to get session sub key").Base(err)
  43. }
  44. }
  45. aead, err := t.method.GetStreamAEAD(sessionKey)
  46. if err != nil {
  47. return newError("failed to get stream AEAD").Base(err)
  48. }
  49. t.c2sAEAD = aead
  50. paddingLength := TCPMinPaddingLength
  51. if initialPayload == nil {
  52. initialPayload = []byte{}
  53. paddingLength += rand.Intn(TCPMaxPaddingLength) // TODO INSECURE RANDOM USED
  54. }
  55. variableLengthHeader := &TCPRequestHeader3VariableLength{
  56. DestinationAddress: address,
  57. Contents: struct {
  58. PaddingLength uint16 `struc:"sizeof=Padding"`
  59. Padding []byte
  60. }(struct {
  61. PaddingLength uint16
  62. Padding []byte
  63. }{
  64. PaddingLength: uint16(paddingLength),
  65. Padding: make([]byte, paddingLength),
  66. }),
  67. }
  68. variableLengthHeaderBuffer := buf.New()
  69. defer variableLengthHeaderBuffer.Release()
  70. {
  71. err := addrParser.WriteAddressPort(variableLengthHeaderBuffer, address, net.Port(destPort))
  72. if err != nil {
  73. return newError("failed to write address port").Base(err)
  74. }
  75. }
  76. {
  77. err := struc.Pack(variableLengthHeaderBuffer, &variableLengthHeader.Contents)
  78. if err != nil {
  79. return newError("failed to pack variable length header").Base(err)
  80. }
  81. }
  82. {
  83. _, err := variableLengthHeaderBuffer.Write(initialPayload)
  84. if err != nil {
  85. return newError("failed to write initial payload").Base(err)
  86. }
  87. }
  88. fixedLengthHeader := &TCPRequestHeader2FixedLength{
  89. Type: TCPHeaderTypeClientToServerStream,
  90. Timestamp: uint64(time.Now().Unix()),
  91. HeaderLength: uint16(variableLengthHeaderBuffer.Len()),
  92. }
  93. fixedLengthHeaderBuffer := buf.New()
  94. defer fixedLengthHeaderBuffer.Release()
  95. {
  96. err := struc.Pack(fixedLengthHeaderBuffer, fixedLengthHeader)
  97. if err != nil {
  98. return newError("failed to pack fixed length header").Base(err)
  99. }
  100. }
  101. eihGenerator := newAESEIHGeneratorContainer(len(eih), effectivePsk, eih)
  102. eihHeader, err := eihGenerator.GenerateEIH(t.keyDerivation, t.method, requestSalt.Bytes())
  103. if err != nil {
  104. return newError("failed to construct EIH").Base(err)
  105. }
  106. preSessionKeyHeader := &TCPRequestHeader1PreSessionKey{
  107. Salt: requestSalt,
  108. EIH: eihHeader,
  109. }
  110. preSessionKeyHeaderBuffer := buf.New()
  111. defer preSessionKeyHeaderBuffer.Release()
  112. {
  113. err := struc.Pack(preSessionKeyHeaderBuffer, preSessionKeyHeader)
  114. if err != nil {
  115. return newError("failed to pack pre session key header").Base(err)
  116. }
  117. }
  118. requestNonce := crypto.GenerateInitialAEADNonce()
  119. t.c2sNonce = requestNonce
  120. {
  121. n, err := out.Write(preSessionKeyHeaderBuffer.BytesFrom(0))
  122. if err != nil {
  123. return newError("failed to write pre session key header").Base(err)
  124. }
  125. if int32(n) != preSessionKeyHeaderBuffer.Len() {
  126. return newError("failed to write pre session key header")
  127. }
  128. }
  129. {
  130. fixedLengthEncrypted := out.Extend(fixedLengthHeaderBuffer.Len() + int32(aead.Overhead()))
  131. aead.Seal(fixedLengthEncrypted[:0], requestNonce(), fixedLengthHeaderBuffer.Bytes(), nil)
  132. }
  133. {
  134. variableLengthEncrypted := out.Extend(variableLengthHeaderBuffer.Len() + int32(aead.Overhead()))
  135. aead.Seal(variableLengthEncrypted[:0], requestNonce(), variableLengthHeaderBuffer.Bytes(), nil)
  136. }
  137. return nil
  138. }
  139. func (t *TCPRequest) DecodeTCPResponseHeader(effectivePsk []byte, in io.Reader) error {
  140. var preSessionKeyHeader TCPResponseHeader1PreSessionKey
  141. preSessionKeyHeader.Salt = newRequestSaltWithLength(t.method.GetSessionSubKeyAndSaltLength())
  142. {
  143. err := struc.Unpack(in, &preSessionKeyHeader)
  144. if err != nil {
  145. return newError("failed to unpack pre session key header").Base(err)
  146. }
  147. }
  148. s2cSalt := preSessionKeyHeader.Salt.Bytes()
  149. t.s2cSalt = preSessionKeyHeader.Salt
  150. sessionKey := make([]byte, t.method.GetSessionSubKeyAndSaltLength())
  151. {
  152. err := t.keyDerivation.GetSessionSubKey(effectivePsk, s2cSalt, sessionKey)
  153. if err != nil {
  154. return newError("failed to get session sub key").Base(err)
  155. }
  156. }
  157. aead, err := t.method.GetStreamAEAD(sessionKey)
  158. if err != nil {
  159. return newError("failed to get stream AEAD").Base(err)
  160. }
  161. t.s2cAEAD = aead
  162. fixedLengthHeaderEncryptedBuffer := buf.New()
  163. defer fixedLengthHeaderEncryptedBuffer.Release()
  164. {
  165. _, err := fixedLengthHeaderEncryptedBuffer.ReadFullFrom(in, 11+int32(t.method.GetSessionSubKeyAndSaltLength())+int32(aead.Overhead()))
  166. if err != nil {
  167. return newError("failed to read fixed length header encrypted").Base(err)
  168. }
  169. }
  170. s2cNonce := crypto.GenerateInitialAEADNonce()
  171. t.s2cNonce = s2cNonce
  172. fixedLengthHeaderDecryptedBuffer := buf.New()
  173. defer fixedLengthHeaderDecryptedBuffer.Release()
  174. {
  175. decryptionBuffer := fixedLengthHeaderDecryptedBuffer.Extend(11 + int32(t.method.GetSessionSubKeyAndSaltLength()))
  176. _, err = aead.Open(decryptionBuffer[:0], s2cNonce(), fixedLengthHeaderEncryptedBuffer.Bytes(), nil)
  177. if err != nil {
  178. return newError("failed to decrypt fixed length header").Base(err)
  179. }
  180. }
  181. var fixedLengthHeader TCPResponseHeader2FixedLength
  182. fixedLengthHeader.RequestSalt = newRequestSaltWithLength(t.method.GetSessionSubKeyAndSaltLength())
  183. {
  184. err := struc.Unpack(bytes.NewReader(fixedLengthHeaderDecryptedBuffer.Bytes()), &fixedLengthHeader)
  185. if err != nil {
  186. return newError("failed to unpack fixed length header").Base(err)
  187. }
  188. }
  189. if fixedLengthHeader.Type != TCPHeaderTypeServerToClientStream {
  190. return newError("unexpected TCP header type")
  191. }
  192. timeDifference := int64(fixedLengthHeader.Timestamp) - time.Now().Unix()
  193. if timeDifference < -30 || timeDifference > 30 {
  194. return newError("timestamp is too far away")
  195. }
  196. t.s2cSaltAssert = fixedLengthHeader.RequestSalt
  197. t.s2cInitialPayloadSize = int(fixedLengthHeader.InitialPayloadLength)
  198. return nil
  199. }
  200. func (t *TCPRequest) CheckC2SConnectionConstraint() error {
  201. if !bytes.Equal(t.c2sSalt.Bytes(), t.s2cSaltAssert.Bytes()) {
  202. return newError("c2s salt not equal to s2c salt assert")
  203. }
  204. return nil
  205. }
  206. func (t *TCPRequest) CreateClientS2CReader(in io.Reader, initialPayload *buf.Buffer) (buf.Reader, error) {
  207. AEADAuthenticator := &crypto.AEADAuthenticator{
  208. AEAD: t.s2cAEAD,
  209. NonceGenerator: t.s2cNonce,
  210. AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
  211. }
  212. initialPayloadEncrypted := buf.NewWithSize(65535)
  213. defer initialPayloadEncrypted.Release()
  214. initialPayloadEncryptedBytes := initialPayloadEncrypted.Extend(int32(t.s2cAEAD.Overhead()) + int32(t.s2cInitialPayloadSize))
  215. _, err := io.ReadFull(in, initialPayloadEncryptedBytes)
  216. if err != nil {
  217. return nil, newError("failed to read initial payload").Base(err)
  218. }
  219. initialPayloadBytes := initialPayload.Extend(int32(t.s2cInitialPayloadSize))
  220. _, err = t.s2cAEAD.Open(initialPayloadBytes[:0], t.s2cNonce(), initialPayloadEncryptedBytes, nil)
  221. if err != nil {
  222. return nil, newError("failed to decrypt initial payload").Base(err)
  223. }
  224. return crypto.NewAuthenticationReader(AEADAuthenticator, &crypto.AEADChunkSizeParser{
  225. Auth: AEADAuthenticator,
  226. }, in, protocol.TransferTypeStream, nil), nil
  227. }
  228. func (t *TCPRequest) CreateClientC2SWriter(writer io.Writer) buf.Writer {
  229. AEADAuthenticator := &crypto.AEADAuthenticator{
  230. AEAD: t.c2sAEAD,
  231. NonceGenerator: t.c2sNonce,
  232. AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
  233. }
  234. sizeParser := &crypto.AEADChunkSizeParser{
  235. Auth: AEADAuthenticator,
  236. }
  237. return crypto.NewAuthenticationWriter(AEADAuthenticator, sizeParser, writer, protocol.TransferTypeStream, nil)
  238. }