reality.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. package tls
  2. import (
  3. "bytes"
  4. "context"
  5. "crypto/aes"
  6. "crypto/cipher"
  7. "crypto/ecdh"
  8. "crypto/ed25519"
  9. "crypto/hmac"
  10. "crypto/sha256"
  11. "crypto/sha512"
  12. "crypto/tls"
  13. "crypto/x509"
  14. "encoding/binary"
  15. "errors"
  16. "net"
  17. "net/http"
  18. "strings"
  19. "time"
  20. "github.com/metacubex/mihomo/log"
  21. "github.com/metacubex/mihomo/ntp"
  22. "github.com/metacubex/randv2"
  23. utls "github.com/metacubex/utls"
  24. "golang.org/x/crypto/chacha20poly1305"
  25. "golang.org/x/crypto/hkdf"
  26. "golang.org/x/net/http2"
  27. )
  28. const RealityMaxShortIDLen = 8
  29. type RealityConfig struct {
  30. PublicKey *ecdh.PublicKey
  31. ShortID [RealityMaxShortIDLen]byte
  32. }
  33. func GetRealityConn(ctx context.Context, conn net.Conn, ClientFingerprint string, tlsConfig *tls.Config, realityConfig *RealityConfig) (net.Conn, error) {
  34. retry := 0
  35. for fingerprint, exists := GetFingerprint(ClientFingerprint); exists; retry++ {
  36. verifier := &realityVerifier{
  37. serverName: tlsConfig.ServerName,
  38. }
  39. uConfig := &utls.Config{
  40. ServerName: tlsConfig.ServerName,
  41. InsecureSkipVerify: true,
  42. SessionTicketsDisabled: true,
  43. VerifyPeerCertificate: verifier.VerifyPeerCertificate,
  44. }
  45. clientID := utls.ClientHelloID{
  46. Client: fingerprint.Client,
  47. Version: fingerprint.Version,
  48. Seed: fingerprint.Seed,
  49. }
  50. uConn := utls.UClient(conn, uConfig, clientID)
  51. verifier.UConn = uConn
  52. err := uConn.BuildHandshakeState()
  53. if err != nil {
  54. return nil, err
  55. }
  56. hello := uConn.HandshakeState.Hello
  57. rawSessionID := hello.Raw[39 : 39+32] // the location of session ID
  58. for i := range rawSessionID { // https://github.com/golang/go/issues/5373
  59. rawSessionID[i] = 0
  60. }
  61. binary.BigEndian.PutUint64(hello.SessionId, uint64(ntp.Now().Unix()))
  62. copy(hello.SessionId[8:], realityConfig.ShortID[:])
  63. hello.SessionId[0] = 1
  64. hello.SessionId[1] = 8
  65. hello.SessionId[2] = 2
  66. //log.Debugln("REALITY hello.sessionId[:16]: %v", hello.SessionId[:16])
  67. ecdheKey := uConn.HandshakeState.State13.EcdheKey
  68. if ecdheKey == nil {
  69. // WTF???
  70. if retry > 2 {
  71. return nil, errors.New("nil ecdheKey")
  72. }
  73. continue // retry
  74. }
  75. authKey, err := ecdheKey.ECDH(realityConfig.PublicKey)
  76. if err != nil {
  77. return nil, err
  78. }
  79. if authKey == nil {
  80. return nil, errors.New("nil auth_key")
  81. }
  82. verifier.authKey = authKey
  83. _, err = hkdf.New(sha256.New, authKey, hello.Random[:20], []byte("REALITY")).Read(authKey)
  84. if err != nil {
  85. return nil, err
  86. }
  87. var aeadCipher cipher.AEAD
  88. if utls.AesgcmPreferred(hello.CipherSuites) {
  89. aesBlock, _ := aes.NewCipher(authKey)
  90. aeadCipher, _ = cipher.NewGCM(aesBlock)
  91. } else {
  92. aeadCipher, _ = chacha20poly1305.New(authKey)
  93. }
  94. aeadCipher.Seal(hello.SessionId[:0], hello.Random[20:], hello.SessionId[:16], hello.Raw)
  95. copy(hello.Raw[39:], hello.SessionId)
  96. //log.Debugln("REALITY hello.sessionId: %v", hello.SessionId)
  97. //log.Debugln("REALITY uConn.AuthKey: %v", authKey)
  98. err = uConn.HandshakeContext(ctx)
  99. if err != nil {
  100. return nil, err
  101. }
  102. log.Debugln("REALITY Authentication: %v, AEAD: %T", verifier.verified, aeadCipher)
  103. if !verifier.verified {
  104. go realityClientFallback(uConn, uConfig.ServerName, clientID)
  105. return nil, errors.New("REALITY authentication failed")
  106. }
  107. return uConn, nil
  108. }
  109. return nil, errors.New("unknown uTLS fingerprint")
  110. }
  111. func realityClientFallback(uConn net.Conn, serverName string, fingerprint utls.ClientHelloID) {
  112. defer uConn.Close()
  113. client := http.Client{
  114. Transport: &http2.Transport{
  115. DialTLSContext: func(ctx context.Context, network, addr string, config *tls.Config) (net.Conn, error) {
  116. return uConn, nil
  117. },
  118. },
  119. }
  120. request, err := http.NewRequest("GET", "https://"+serverName, nil)
  121. if err != nil {
  122. return
  123. }
  124. request.Header.Set("User-Agent", fingerprint.Client)
  125. request.AddCookie(&http.Cookie{Name: "padding", Value: strings.Repeat("0", randv2.IntN(32)+30)})
  126. response, err := client.Do(request)
  127. if err != nil {
  128. return
  129. }
  130. //_, _ = io.Copy(io.Discard, response.Body)
  131. time.Sleep(time.Duration(5+randv2.IntN(10)) * time.Second)
  132. response.Body.Close()
  133. client.CloseIdleConnections()
  134. }
  135. type realityVerifier struct {
  136. *utls.UConn
  137. serverName string
  138. authKey []byte
  139. verified bool
  140. }
  141. //var pOffset = utils.MustOK(reflect.TypeOf((*utls.Conn)(nil)).Elem().FieldByName("peerCertificates")).Offset
  142. func (c *realityVerifier) VerifyPeerCertificate(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
  143. //p, _ := reflect.TypeOf(c.Conn).Elem().FieldByName("peerCertificates")
  144. //certs := *(*[]*x509.Certificate)(unsafe.Add(unsafe.Pointer(c.Conn), pOffset))
  145. certs := c.Conn.PeerCertificates()
  146. if pub, ok := certs[0].PublicKey.(ed25519.PublicKey); ok {
  147. h := hmac.New(sha512.New, c.authKey)
  148. h.Write(pub)
  149. if bytes.Equal(h.Sum(nil), certs[0].Signature) {
  150. c.verified = true
  151. return nil
  152. }
  153. }
  154. opts := x509.VerifyOptions{
  155. DNSName: c.serverName,
  156. Intermediates: x509.NewCertPool(),
  157. }
  158. for _, cert := range certs[1:] {
  159. opts.Intermediates.AddCert(cert)
  160. }
  161. if _, err := certs[0].Verify(opts); err != nil {
  162. return err
  163. }
  164. return nil
  165. }