shadowtls.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. package shadowtls
  2. import (
  3. "context"
  4. "crypto/hmac"
  5. "crypto/sha1"
  6. "crypto/tls"
  7. "encoding/binary"
  8. "fmt"
  9. "hash"
  10. "io"
  11. "net"
  12. "github.com/metacubex/mihomo/common/pool"
  13. C "github.com/metacubex/mihomo/constant"
  14. )
  15. const (
  16. chunkSize = 1 << 13
  17. Mode string = "shadow-tls"
  18. hashLen int = 8
  19. tlsHeaderLen int = 5
  20. )
  21. var (
  22. DefaultALPN = []string{"h2", "http/1.1"}
  23. )
  24. // ShadowTLS is shadow-tls implementation
  25. type ShadowTLS struct {
  26. net.Conn
  27. password []byte
  28. remain int
  29. firstRequest bool
  30. tlsConfig *tls.Config
  31. }
  32. type HashedConn struct {
  33. net.Conn
  34. hasher hash.Hash
  35. }
  36. func newHashedStream(conn net.Conn, password []byte) HashedConn {
  37. return HashedConn{
  38. Conn: conn,
  39. hasher: hmac.New(sha1.New, password),
  40. }
  41. }
  42. func (h HashedConn) Read(b []byte) (n int, err error) {
  43. n, err = h.Conn.Read(b)
  44. h.hasher.Write(b[:n])
  45. return
  46. }
  47. func (s *ShadowTLS) read(b []byte) (int, error) {
  48. var buf [tlsHeaderLen]byte
  49. _, err := io.ReadFull(s.Conn, buf[:])
  50. if err != nil {
  51. return 0, fmt.Errorf("shadowtls read failed %w", err)
  52. }
  53. if buf[0] != 0x17 || buf[1] != 0x3 || buf[2] != 0x3 {
  54. return 0, fmt.Errorf("invalid shadowtls header %v", buf)
  55. }
  56. length := int(binary.BigEndian.Uint16(buf[3:]))
  57. if length > len(b) {
  58. n, err := s.Conn.Read(b)
  59. if err != nil {
  60. return n, err
  61. }
  62. s.remain = length - n
  63. return n, nil
  64. }
  65. return io.ReadFull(s.Conn, b[:length])
  66. }
  67. func (s *ShadowTLS) Read(b []byte) (int, error) {
  68. if s.remain > 0 {
  69. length := s.remain
  70. if length > len(b) {
  71. length = len(b)
  72. }
  73. n, err := io.ReadFull(s.Conn, b[:length])
  74. if err != nil {
  75. return n, fmt.Errorf("shadowtls Read failed with %w", err)
  76. }
  77. s.remain -= n
  78. return n, nil
  79. }
  80. return s.read(b)
  81. }
  82. func (s *ShadowTLS) Write(b []byte) (int, error) {
  83. length := len(b)
  84. for i := 0; i < length; i += chunkSize {
  85. end := i + chunkSize
  86. if end > length {
  87. end = length
  88. }
  89. n, err := s.write(b[i:end])
  90. if err != nil {
  91. return n, fmt.Errorf("shadowtls Write failed with %w, i=%d, end=%d, n=%d", err, i, end, n)
  92. }
  93. }
  94. return length, nil
  95. }
  96. func (s *ShadowTLS) write(b []byte) (int, error) {
  97. var hashVal []byte
  98. if s.firstRequest {
  99. hashedConn := newHashedStream(s.Conn, s.password)
  100. tlsConn := tls.Client(hashedConn, s.tlsConfig)
  101. // fix tls handshake not timeout
  102. ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout)
  103. defer cancel()
  104. if err := tlsConn.HandshakeContext(ctx); err != nil {
  105. return 0, fmt.Errorf("tls connect failed with %w", err)
  106. }
  107. hashVal = hashedConn.hasher.Sum(nil)[:hashLen]
  108. s.firstRequest = false
  109. }
  110. buf := pool.GetBuffer()
  111. defer pool.PutBuffer(buf)
  112. buf.Write([]byte{0x17, 0x03, 0x03})
  113. binary.Write(buf, binary.BigEndian, uint16(len(b)+len(hashVal)))
  114. buf.Write(hashVal)
  115. buf.Write(b)
  116. _, err := s.Conn.Write(buf.Bytes())
  117. if err != nil {
  118. // return 0 because errors occur here make the
  119. // whole situation irrecoverable
  120. return 0, err
  121. }
  122. return len(b), nil
  123. }
  124. // NewShadowTLS return a ShadowTLS
  125. func NewShadowTLS(conn net.Conn, password string, tlsConfig *tls.Config) net.Conn {
  126. return &ShadowTLS{
  127. Conn: conn,
  128. password: []byte(password),
  129. firstRequest: true,
  130. tlsConfig: tlsConfig,
  131. }
  132. }