utls_client.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. //go:build with_utls
  2. package tls
  3. import (
  4. "context"
  5. "crypto/tls"
  6. "crypto/x509"
  7. "math/rand"
  8. "net"
  9. "os"
  10. "strings"
  11. "time"
  12. "github.com/sagernet/sing-box/adapter"
  13. "github.com/sagernet/sing-box/common/tlsfragment"
  14. "github.com/sagernet/sing-box/common/tlsspoof"
  15. C "github.com/sagernet/sing-box/constant"
  16. "github.com/sagernet/sing-box/option"
  17. "github.com/sagernet/sing/common"
  18. E "github.com/sagernet/sing/common/exceptions"
  19. "github.com/sagernet/sing/common/logger"
  20. "github.com/sagernet/sing/common/ntp"
  21. utls "github.com/metacubex/utls"
  22. "golang.org/x/net/http2"
  23. )
  24. type UTLSClientConfig struct {
  25. ctx context.Context
  26. config *utls.Config
  27. serverName string
  28. disableSNI bool
  29. verifyServerName bool
  30. handshakeTimeout time.Duration
  31. id utls.ClientHelloID
  32. fragment bool
  33. fragmentFallbackDelay time.Duration
  34. recordFragment bool
  35. spoof string
  36. spoofMethod tlsspoof.Method
  37. }
  38. func (c *UTLSClientConfig) ServerName() string {
  39. return c.serverName
  40. }
  41. func (c *UTLSClientConfig) SetServerName(serverName string) {
  42. c.serverName = serverName
  43. if c.disableSNI {
  44. c.config.ServerName = ""
  45. if c.verifyServerName {
  46. c.config.InsecureServerNameToVerify = serverName
  47. } else {
  48. c.config.InsecureServerNameToVerify = ""
  49. }
  50. return
  51. }
  52. c.config.ServerName = serverName
  53. }
  54. func (c *UTLSClientConfig) NextProtos() []string {
  55. return c.config.NextProtos
  56. }
  57. func (c *UTLSClientConfig) SetNextProtos(nextProto []string) {
  58. if len(nextProto) == 1 && nextProto[0] == http2.NextProtoTLS {
  59. nextProto = append(nextProto, "http/1.1")
  60. }
  61. c.config.NextProtos = nextProto
  62. }
  63. func (c *UTLSClientConfig) HandshakeTimeout() time.Duration {
  64. return c.handshakeTimeout
  65. }
  66. func (c *UTLSClientConfig) SetHandshakeTimeout(timeout time.Duration) {
  67. c.handshakeTimeout = timeout
  68. }
  69. func (c *UTLSClientConfig) STDConfig() (*STDConfig, error) {
  70. return nil, E.New("unsupported usage for uTLS")
  71. }
  72. func (c *UTLSClientConfig) Client(conn net.Conn) (Conn, error) {
  73. if c.fragment || c.recordFragment {
  74. conn = tf.NewConn(conn, c.ctx, c.fragment, c.recordFragment, c.fragmentFallbackDelay)
  75. }
  76. conn, err := applyTLSSpoof(conn, c.spoof, c.spoofMethod)
  77. if err != nil {
  78. return nil, err
  79. }
  80. return &utlsALPNWrapper{utlsConnWrapper{utls.UClient(conn, c.config.Clone(), c.id)}, c.config.NextProtos}, nil
  81. }
  82. func (c *UTLSClientConfig) SetSessionIDGenerator(generator func(clientHello []byte, sessionID []byte) error) {
  83. c.config.SessionIDGenerator = generator
  84. }
  85. func (c *UTLSClientConfig) Clone() Config {
  86. cloned := &UTLSClientConfig{
  87. ctx: c.ctx,
  88. config: c.config.Clone(),
  89. serverName: c.serverName,
  90. disableSNI: c.disableSNI,
  91. verifyServerName: c.verifyServerName,
  92. handshakeTimeout: c.handshakeTimeout,
  93. id: c.id,
  94. fragment: c.fragment,
  95. fragmentFallbackDelay: c.fragmentFallbackDelay,
  96. recordFragment: c.recordFragment,
  97. spoof: c.spoof,
  98. spoofMethod: c.spoofMethod,
  99. }
  100. cloned.SetServerName(cloned.serverName)
  101. return cloned
  102. }
  103. func (c *UTLSClientConfig) ECHConfigList() []byte {
  104. return c.config.EncryptedClientHelloConfigList
  105. }
  106. func (c *UTLSClientConfig) SetECHConfigList(EncryptedClientHelloConfigList []byte) {
  107. c.config.EncryptedClientHelloConfigList = EncryptedClientHelloConfigList
  108. }
  109. type utlsConnWrapper struct {
  110. *utls.UConn
  111. }
  112. func (c *utlsConnWrapper) ConnectionState() tls.ConnectionState {
  113. state := c.Conn.ConnectionState()
  114. //nolint:staticcheck
  115. return tls.ConnectionState{
  116. Version: state.Version,
  117. HandshakeComplete: state.HandshakeComplete,
  118. DidResume: state.DidResume,
  119. CipherSuite: state.CipherSuite,
  120. NegotiatedProtocol: state.NegotiatedProtocol,
  121. NegotiatedProtocolIsMutual: state.NegotiatedProtocolIsMutual,
  122. ServerName: state.ServerName,
  123. PeerCertificates: state.PeerCertificates,
  124. VerifiedChains: state.VerifiedChains,
  125. SignedCertificateTimestamps: state.SignedCertificateTimestamps,
  126. OCSPResponse: state.OCSPResponse,
  127. TLSUnique: state.TLSUnique,
  128. }
  129. }
  130. func (c *utlsConnWrapper) Upstream() any {
  131. return c.UConn
  132. }
  133. func (c *utlsConnWrapper) ReaderReplaceable() bool {
  134. return true
  135. }
  136. func (c *utlsConnWrapper) WriterReplaceable() bool {
  137. return true
  138. }
  139. type utlsALPNWrapper struct {
  140. utlsConnWrapper
  141. nextProtocols []string
  142. }
  143. func (c *utlsALPNWrapper) HandshakeContext(ctx context.Context) error {
  144. if len(c.nextProtocols) > 0 {
  145. err := c.BuildHandshakeState()
  146. if err != nil {
  147. return err
  148. }
  149. for _, extension := range c.Extensions {
  150. if alpnExtension, isALPN := extension.(*utls.ALPNExtension); isALPN {
  151. alpnExtension.AlpnProtocols = c.nextProtocols
  152. err = c.BuildHandshakeState()
  153. if err != nil {
  154. return err
  155. }
  156. break
  157. }
  158. }
  159. }
  160. return c.UConn.HandshakeContext(ctx)
  161. }
  162. func NewUTLSClient(ctx context.Context, logger logger.ContextLogger, serverAddress string, options option.OutboundTLSOptions) (Config, error) {
  163. return newUTLSClient(ctx, logger, serverAddress, options, false)
  164. }
  165. func newUTLSClient(ctx context.Context, logger logger.ContextLogger, serverAddress string, options option.OutboundTLSOptions, allowEmptyServerName bool) (Config, error) {
  166. var serverName string
  167. if options.ServerName != "" {
  168. serverName = options.ServerName
  169. } else if serverAddress != "" {
  170. serverName = serverAddress
  171. }
  172. if serverName == "" && !options.Insecure && !allowEmptyServerName {
  173. return nil, errMissingServerName
  174. }
  175. var tlsConfig utls.Config
  176. tlsConfig.Time = ntp.TimeFuncFromContext(ctx)
  177. tlsConfig.RootCAs = adapter.RootPoolFromContext(ctx)
  178. if options.Insecure {
  179. tlsConfig.InsecureSkipVerify = options.Insecure
  180. } else if options.DisableSNI {
  181. if options.Reality != nil && options.Reality.Enabled {
  182. return nil, E.New("disable_sni is unsupported in reality")
  183. }
  184. }
  185. if len(options.CertificatePublicKeySHA256) > 0 {
  186. if len(options.Certificate) > 0 || options.CertificatePath != "" {
  187. return nil, E.New("certificate_public_key_sha256 is conflict with certificate or certificate_path")
  188. }
  189. tlsConfig.InsecureSkipVerify = true
  190. tlsConfig.VerifyPeerCertificate = func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
  191. return VerifyPublicKeySHA256(options.CertificatePublicKeySHA256, rawCerts)
  192. }
  193. }
  194. if len(options.ALPN) > 0 {
  195. tlsConfig.NextProtos = options.ALPN
  196. }
  197. if options.MinVersion != "" {
  198. minVersion, err := ParseTLSVersion(options.MinVersion)
  199. if err != nil {
  200. return nil, E.Cause(err, "parse min_version")
  201. }
  202. tlsConfig.MinVersion = minVersion
  203. }
  204. if options.MaxVersion != "" {
  205. maxVersion, err := ParseTLSVersion(options.MaxVersion)
  206. if err != nil {
  207. return nil, E.Cause(err, "parse max_version")
  208. }
  209. tlsConfig.MaxVersion = maxVersion
  210. }
  211. if options.CipherSuites != nil {
  212. find:
  213. for _, cipherSuite := range options.CipherSuites {
  214. for _, tlsCipherSuite := range tls.CipherSuites() {
  215. if cipherSuite == tlsCipherSuite.Name {
  216. tlsConfig.CipherSuites = append(tlsConfig.CipherSuites, tlsCipherSuite.ID)
  217. continue find
  218. }
  219. }
  220. return nil, E.New("unknown cipher_suite: ", cipherSuite)
  221. }
  222. }
  223. var certificate []byte
  224. if len(options.Certificate) > 0 {
  225. certificate = []byte(strings.Join(options.Certificate, "\n"))
  226. } else if options.CertificatePath != "" {
  227. content, err := os.ReadFile(options.CertificatePath)
  228. if err != nil {
  229. return nil, E.Cause(err, "read certificate")
  230. }
  231. certificate = content
  232. }
  233. if len(certificate) > 0 {
  234. certPool := x509.NewCertPool()
  235. if !certPool.AppendCertsFromPEM(certificate) {
  236. return nil, E.New("failed to parse certificate:\n\n", certificate)
  237. }
  238. tlsConfig.RootCAs = certPool
  239. }
  240. var clientCertificate []byte
  241. if len(options.ClientCertificate) > 0 {
  242. clientCertificate = []byte(strings.Join(options.ClientCertificate, "\n"))
  243. } else if options.ClientCertificatePath != "" {
  244. content, err := os.ReadFile(options.ClientCertificatePath)
  245. if err != nil {
  246. return nil, E.Cause(err, "read client certificate")
  247. }
  248. clientCertificate = content
  249. }
  250. var clientKey []byte
  251. if len(options.ClientKey) > 0 {
  252. clientKey = []byte(strings.Join(options.ClientKey, "\n"))
  253. } else if options.ClientKeyPath != "" {
  254. content, err := os.ReadFile(options.ClientKeyPath)
  255. if err != nil {
  256. return nil, E.Cause(err, "read client key")
  257. }
  258. clientKey = content
  259. }
  260. if len(clientCertificate) > 0 && len(clientKey) > 0 {
  261. keyPair, err := utls.X509KeyPair(clientCertificate, clientKey)
  262. if err != nil {
  263. return nil, E.Cause(err, "parse client x509 key pair")
  264. }
  265. tlsConfig.Certificates = []utls.Certificate{keyPair}
  266. } else if len(clientCertificate) > 0 || len(clientKey) > 0 {
  267. return nil, E.New("client certificate and client key must be provided together")
  268. }
  269. var handshakeTimeout time.Duration
  270. if options.HandshakeTimeout > 0 {
  271. handshakeTimeout = options.HandshakeTimeout.Build()
  272. } else {
  273. handshakeTimeout = C.TCPTimeout
  274. }
  275. spoof, spoofMethod, err := parseTLSSpoofOptions(serverName, options)
  276. if err != nil {
  277. return nil, err
  278. }
  279. id, err := uTLSClientHelloID(options.UTLS.Fingerprint)
  280. if err != nil {
  281. return nil, err
  282. }
  283. var config Config = &UTLSClientConfig{
  284. ctx: ctx,
  285. config: &tlsConfig,
  286. serverName: serverName,
  287. disableSNI: options.DisableSNI,
  288. verifyServerName: options.DisableSNI && !options.Insecure,
  289. handshakeTimeout: handshakeTimeout,
  290. id: id,
  291. fragment: options.Fragment,
  292. fragmentFallbackDelay: time.Duration(options.FragmentFallbackDelay),
  293. recordFragment: options.RecordFragment,
  294. spoof: spoof,
  295. spoofMethod: spoofMethod,
  296. }
  297. config.SetServerName(serverName)
  298. if options.ECH != nil && options.ECH.Enabled {
  299. if options.Reality != nil && options.Reality.Enabled {
  300. return nil, E.New("Reality is conflict with ECH")
  301. }
  302. config, err = parseECHClientConfig(ctx, config.(ECHCapableConfig), options)
  303. if err != nil {
  304. return nil, err
  305. }
  306. }
  307. if (options.KernelRx || options.KernelTx) && !common.PtrValueOrDefault(options.Reality).Enabled {
  308. if !C.IsLinux {
  309. return nil, E.New("kTLS is only supported on Linux")
  310. }
  311. config = &KTLSClientConfig{
  312. Config: config,
  313. logger: logger,
  314. kernelTx: options.KernelTx,
  315. kernelRx: options.KernelRx,
  316. }
  317. }
  318. return config, nil
  319. }
  320. var (
  321. randomFingerprint utls.ClientHelloID
  322. randomizedFingerprint utls.ClientHelloID
  323. )
  324. func init() {
  325. modernFingerprints := []utls.ClientHelloID{
  326. utls.HelloChrome_Auto,
  327. utls.HelloFirefox_Auto,
  328. utls.HelloEdge_Auto,
  329. utls.HelloSafari_Auto,
  330. utls.HelloIOS_Auto,
  331. }
  332. randomFingerprint = modernFingerprints[rand.Intn(len(modernFingerprints))]
  333. weights := utls.DefaultWeights
  334. weights.TLSVersMax_Set_VersionTLS13 = 1
  335. weights.FirstKeyShare_Set_CurveP256 = 0
  336. randomizedFingerprint = utls.HelloRandomized
  337. randomizedFingerprint.Seed, _ = utls.NewPRNGSeed()
  338. randomizedFingerprint.Weights = &weights
  339. }
  340. func uTLSClientHelloID(name string) (utls.ClientHelloID, error) {
  341. switch name {
  342. case "chrome_psk", "chrome_psk_shuffle", "chrome_padding_psk_shuffle", "chrome_pq", "chrome_pq_psk":
  343. fallthrough
  344. case "chrome", "":
  345. return utls.HelloChrome_Auto, nil
  346. case "firefox":
  347. return utls.HelloFirefox_Auto, nil
  348. case "edge":
  349. return utls.HelloEdge_Auto, nil
  350. case "safari":
  351. return utls.HelloSafari_Auto, nil
  352. case "360":
  353. return utls.Hello360_Auto, nil
  354. case "qq":
  355. return utls.HelloQQ_Auto, nil
  356. case "ios":
  357. return utls.HelloIOS_Auto, nil
  358. case "android":
  359. return utls.HelloAndroid_11_OkHttp, nil
  360. case "random":
  361. return randomFingerprint, nil
  362. case "randomized":
  363. return randomizedFingerprint, nil
  364. default:
  365. return utls.ClientHelloID{}, E.New("unknown uTLS fingerprint: ", name)
  366. }
  367. }