encoding.go 8.4 KB

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