tlsDialer.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758
  1. /*
  2. * Copyright (c) 2015, Psiphon Inc.
  3. * All rights reserved.
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. */
  19. /*
  20. Copyright (c) 2012 The Go Authors. All rights reserved.
  21. Redistribution and use in source and binary forms, with or without
  22. modification, are permitted provided that the following conditions are
  23. met:
  24. * Redistributions of source code must retain the above copyright
  25. notice, this list of conditions and the following disclaimer.
  26. * Redistributions in binary form must reproduce the above
  27. copyright notice, this list of conditions and the following disclaimer
  28. in the documentation and/or other materials provided with the
  29. distribution.
  30. * Neither the name of Google Inc. nor the names of its
  31. contributors may be used to endorse or promote products derived from
  32. this software without specific prior written permission.
  33. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  34. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  35. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  36. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  37. OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  38. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  39. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  40. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  41. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  42. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  43. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  44. */
  45. // Based on https://github.com/getlantern/tlsdialer (http://gopkg.in/getlantern/tlsdialer.v1)
  46. // which itself is a "Fork of crypto/tls.Dial and DialWithDialer"
  47. package psiphon
  48. import (
  49. "bytes"
  50. "context"
  51. "crypto/x509"
  52. "encoding/hex"
  53. std_errors "errors"
  54. "io/ioutil"
  55. "net"
  56. "time"
  57. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
  58. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
  59. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
  60. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
  61. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
  62. tris "github.com/Psiphon-Labs/tls-tris"
  63. utls "github.com/refraction-networking/utls"
  64. )
  65. // CustomTLSConfig contains parameters to determine the behavior
  66. // of CustomTLSDial.
  67. type CustomTLSConfig struct {
  68. // ClientParameters is the active set of client parameters to use
  69. // for the TLS dial.
  70. ClientParameters *parameters.ClientParameters
  71. // Dial is the network connection dialer. TLS is layered on
  72. // top of a new network connection created with dialer.
  73. Dial Dialer
  74. // DialAddr overrides the "addr" input to Dial when specified
  75. DialAddr string
  76. // UseDialAddrSNI specifies whether to always use the dial "addr"
  77. // host name in the SNI server_name field. When DialAddr is set,
  78. // its host name is used.
  79. UseDialAddrSNI bool
  80. // SNIServerName specifies the value to set in the SNI
  81. // server_name field. When blank, SNI is omitted. Note that
  82. // underlying TLS code also automatically omits SNI when
  83. // the server_name is an IP address.
  84. // SNIServerName is ignored when UseDialAddrSNI is true.
  85. SNIServerName string
  86. // SkipVerify completely disables server certificate verification.
  87. SkipVerify bool
  88. // VerifyLegacyCertificate is a special case self-signed server
  89. // certificate case. Ignores IP SANs and basic constraints. No
  90. // certificate chain. Just checks that the server presented the
  91. // specified certificate. SNI is disbled when this is set.
  92. VerifyLegacyCertificate *x509.Certificate
  93. // TLSProfile specifies a particular indistinguishable TLS profile to use for
  94. // the TLS dial. Setting TLSProfile allows the caller to pin the selection so
  95. // all TLS connections in a certain context (e.g. a single meek connection)
  96. // use a consistent value. The value should be selected by calling
  97. // SelectTLSProfile, which will pick a value at random, subject to
  98. // compatibility constraints.
  99. //
  100. // When TLSProfile is "", a profile is selected at random and
  101. // DisableFrontingProviderTLSProfiles is ignored.
  102. TLSProfile string
  103. // NoDefaultTLSSessionID specifies whether to set a TLS session ID by
  104. // default, for a new TLS connection that is not resuming a session.
  105. // When nil, the parameter is set randomly.
  106. NoDefaultTLSSessionID *bool
  107. // RandomizedTLSProfileSeed specifies the PRNG seed to use when generating
  108. // a randomized TLS ClientHello, which applies to TLS profiles where
  109. // protocol.TLSProfileIsRandomized is true. The PRNG seed allows for
  110. // optional replay of a particular randomized Client Hello.
  111. RandomizedTLSProfileSeed *prng.Seed
  112. // TLSPadding indicates whether to move or add a TLS padding extension to the
  113. // front of the exension list and apply the specified padding length. Ignored
  114. // when 0.
  115. TLSPadding int
  116. // TrustedCACertificatesFilename specifies a file containing trusted
  117. // CA certs. See Config.TrustedCACertificatesFilename.
  118. TrustedCACertificatesFilename string
  119. // ObfuscatedSessionTicketKey enables obfuscated session tickets
  120. // using the specified key.
  121. ObfuscatedSessionTicketKey string
  122. // PassthroughMessage, when specified, is a 32 byte value that is sent in the
  123. // ClientHello random value field. The value should be generated using
  124. // obfuscator.MakeTLSPassthroughMessage.
  125. PassthroughMessage []byte
  126. clientSessionCache utls.ClientSessionCache
  127. }
  128. // EnableClientSessionCache initializes a cache to use to persist session
  129. // tickets, enabling TLS session resumability across multiple
  130. // CustomTLSDial calls or dialers using the same CustomTLSConfig.
  131. func (config *CustomTLSConfig) EnableClientSessionCache() {
  132. if config.clientSessionCache == nil {
  133. config.clientSessionCache = utls.NewLRUClientSessionCache(0)
  134. }
  135. }
  136. // SelectTLSProfile picks a TLS profile at random from the available candidates.
  137. func SelectTLSProfile(
  138. requireTLS12SessionTickets bool,
  139. isFronted bool,
  140. frontingProviderID string,
  141. p parameters.ClientParametersAccessor) string {
  142. // Two TLS profile lists are constructed, subject to limit constraints:
  143. // stock, fixed parrots (non-randomized SupportedTLSProfiles) and custom
  144. // parrots (CustomTLSProfileNames); and randomized. If one list is empty, the
  145. // non-empty list is used. Otherwise SelectRandomizedTLSProfileProbability
  146. // determines which list is used.
  147. //
  148. // Note that LimitTLSProfiles is not applied to CustomTLSProfiles; the
  149. // presence of a candidate in CustomTLSProfiles is treated as explicit
  150. // enabling.
  151. //
  152. // UseOnlyCustomTLSProfiles may be used to disable all stock TLS profiles and
  153. // use only CustomTLSProfiles; UseOnlyCustomTLSProfiles is ignored if
  154. // CustomTLSProfiles is empty.
  155. //
  156. // For fronted servers, DisableFrontingProviderTLSProfiles may be used
  157. // to disable TLS profiles which are incompatible with the TLS stack used
  158. // by the front. For example, if a utls parrot doesn't fully support all
  159. // of the capabilities in the ClientHello. Unlike the LimitTLSProfiles case,
  160. // DisableFrontingProviderTLSProfiles may disable CustomTLSProfiles.
  161. limitTLSProfiles := p.TLSProfiles(parameters.LimitTLSProfiles)
  162. var disableTLSProfiles protocol.TLSProfiles
  163. if isFronted && frontingProviderID != "" {
  164. disableTLSProfiles = p.LabeledTLSProfiles(
  165. parameters.DisableFrontingProviderTLSProfiles, frontingProviderID)
  166. }
  167. randomizedTLSProfiles := make([]string, 0)
  168. parrotTLSProfiles := make([]string, 0)
  169. for _, tlsProfile := range p.CustomTLSProfileNames() {
  170. if !common.Contains(disableTLSProfiles, tlsProfile) {
  171. parrotTLSProfiles = append(parrotTLSProfiles, tlsProfile)
  172. }
  173. }
  174. useOnlyCustomTLSProfiles := p.Bool(parameters.UseOnlyCustomTLSProfiles)
  175. if useOnlyCustomTLSProfiles && len(parrotTLSProfiles) == 0 {
  176. useOnlyCustomTLSProfiles = false
  177. }
  178. if !useOnlyCustomTLSProfiles {
  179. for _, tlsProfile := range protocol.SupportedTLSProfiles {
  180. if len(limitTLSProfiles) > 0 &&
  181. !common.Contains(limitTLSProfiles, tlsProfile) {
  182. continue
  183. }
  184. if common.Contains(disableTLSProfiles, tlsProfile) {
  185. continue
  186. }
  187. // requireTLS12SessionTickets is specified for
  188. // UNFRONTED-MEEK-SESSION-TICKET-OSSH, a protocol which depends on using
  189. // obfuscated session tickets to ensure that the server doesn't send its
  190. // certificate in the TLS handshake. TLS 1.2 profiles which omit session
  191. // tickets should not be selected. As TLS 1.3 encrypts the server
  192. // certificate message, there's no exclusion for TLS 1.3.
  193. if requireTLS12SessionTickets &&
  194. protocol.TLS12ProfileOmitsSessionTickets(tlsProfile) {
  195. continue
  196. }
  197. if protocol.TLSProfileIsRandomized(tlsProfile) {
  198. randomizedTLSProfiles = append(randomizedTLSProfiles, tlsProfile)
  199. } else {
  200. parrotTLSProfiles = append(parrotTLSProfiles, tlsProfile)
  201. }
  202. }
  203. }
  204. if len(randomizedTLSProfiles) > 0 &&
  205. (len(parrotTLSProfiles) == 0 ||
  206. p.WeightedCoinFlip(parameters.SelectRandomizedTLSProfileProbability)) {
  207. return randomizedTLSProfiles[prng.Intn(len(randomizedTLSProfiles))]
  208. }
  209. if len(parrotTLSProfiles) == 0 {
  210. return ""
  211. }
  212. return parrotTLSProfiles[prng.Intn(len(parrotTLSProfiles))]
  213. }
  214. func getUTLSClientHelloID(
  215. p parameters.ClientParametersAccessor,
  216. tlsProfile string) (utls.ClientHelloID, *utls.ClientHelloSpec, error) {
  217. switch tlsProfile {
  218. case protocol.TLS_PROFILE_IOS_111:
  219. return utls.HelloIOS_11_1, nil, nil
  220. case protocol.TLS_PROFILE_IOS_121:
  221. return utls.HelloIOS_12_1, nil, nil
  222. case protocol.TLS_PROFILE_CHROME_58:
  223. return utls.HelloChrome_58, nil, nil
  224. case protocol.TLS_PROFILE_CHROME_62:
  225. return utls.HelloChrome_62, nil, nil
  226. case protocol.TLS_PROFILE_CHROME_70:
  227. return utls.HelloChrome_70, nil, nil
  228. case protocol.TLS_PROFILE_CHROME_72:
  229. return utls.HelloChrome_72, nil, nil
  230. case protocol.TLS_PROFILE_CHROME_83:
  231. return utls.HelloChrome_83, nil, nil
  232. case protocol.TLS_PROFILE_FIREFOX_55:
  233. return utls.HelloFirefox_55, nil, nil
  234. case protocol.TLS_PROFILE_FIREFOX_56:
  235. return utls.HelloFirefox_56, nil, nil
  236. case protocol.TLS_PROFILE_FIREFOX_65:
  237. return utls.HelloFirefox_65, nil, nil
  238. case protocol.TLS_PROFILE_RANDOMIZED:
  239. return utls.HelloRandomized, nil, nil
  240. }
  241. // utls.HelloCustom with a utls.ClientHelloSpec is used for
  242. // CustomTLSProfiles.
  243. customTLSProfile := p.CustomTLSProfile(tlsProfile)
  244. if customTLSProfile == nil {
  245. return utls.HelloCustom,
  246. nil,
  247. errors.Tracef("unknown TLS profile: %s", tlsProfile)
  248. }
  249. utlsClientHelloSpec, err := customTLSProfile.GetClientHelloSpec()
  250. if err != nil {
  251. return utls.ClientHelloID{}, nil, errors.Trace(err)
  252. }
  253. return utls.HelloCustom, utlsClientHelloSpec, nil
  254. }
  255. func getClientHelloVersion(
  256. utlsClientHelloID utls.ClientHelloID,
  257. utlsClientHelloSpec *utls.ClientHelloSpec) (string, error) {
  258. switch utlsClientHelloID {
  259. case utls.HelloIOS_11_1, utls.HelloIOS_12_1, utls.HelloChrome_58,
  260. utls.HelloChrome_62, utls.HelloFirefox_55, utls.HelloFirefox_56:
  261. return protocol.TLS_VERSION_12, nil
  262. case utls.HelloChrome_70, utls.HelloChrome_72, utls.HelloChrome_83,
  263. utls.HelloFirefox_65, utls.HelloGolang:
  264. return protocol.TLS_VERSION_13, nil
  265. }
  266. // As utls.HelloRandomized/Custom may be either TLS 1.2 or TLS 1.3, we cannot
  267. // perform a simple ClientHello ID check. BuildHandshakeState is run, which
  268. // constructs the entire ClientHello.
  269. //
  270. // Assumes utlsClientHelloID.Seed has been set; otherwise the result is
  271. // ephemeral.
  272. //
  273. // BenchmarkRandomizedGetClientHelloVersion indicates that this operation
  274. // takes on the order of 0.05ms and allocates ~8KB for randomized client
  275. // hellos.
  276. conn := utls.UClient(
  277. nil,
  278. &utls.Config{InsecureSkipVerify: true},
  279. utlsClientHelloID)
  280. if utlsClientHelloSpec != nil {
  281. err := conn.ApplyPreset(utlsClientHelloSpec)
  282. if err != nil {
  283. return "", errors.Trace(err)
  284. }
  285. }
  286. err := conn.BuildHandshakeState()
  287. if err != nil {
  288. return "", errors.Trace(err)
  289. }
  290. for _, v := range conn.HandshakeState.Hello.SupportedVersions {
  291. if v == utls.VersionTLS13 {
  292. return protocol.TLS_VERSION_13, nil
  293. }
  294. }
  295. return protocol.TLS_VERSION_12, nil
  296. }
  297. func IsTLSConnUsingHTTP2(conn net.Conn) bool {
  298. if c, ok := conn.(*utls.UConn); ok {
  299. state := c.ConnectionState()
  300. return state.NegotiatedProtocolIsMutual &&
  301. state.NegotiatedProtocol == "h2"
  302. }
  303. return false
  304. }
  305. // NewCustomTLSDialer creates a new dialer based on CustomTLSDial.
  306. func NewCustomTLSDialer(config *CustomTLSConfig) Dialer {
  307. return func(ctx context.Context, network, addr string) (net.Conn, error) {
  308. return CustomTLSDial(ctx, network, addr, config)
  309. }
  310. }
  311. // CustomTLSDial is a customized replacement for tls.Dial.
  312. // Based on tlsdialer.DialWithDialer which is based on crypto/tls.DialWithDialer.
  313. //
  314. // To ensure optimal TLS profile selection when using CustomTLSDial for tunnel
  315. // protocols, call SelectTLSProfile first and set its result into
  316. // config.TLSProfile.
  317. //
  318. // tlsdialer comment:
  319. // Note - if sendServerName is false, the VerifiedChains field on the
  320. // connection's ConnectionState will never get populated.
  321. func CustomTLSDial(
  322. ctx context.Context,
  323. network, addr string,
  324. config *CustomTLSConfig) (net.Conn, error) {
  325. p := config.ClientParameters.Get()
  326. dialAddr := addr
  327. if config.DialAddr != "" {
  328. dialAddr = config.DialAddr
  329. }
  330. rawConn, err := config.Dial(ctx, network, dialAddr)
  331. if err != nil {
  332. return nil, errors.Trace(err)
  333. }
  334. hostname, _, err := net.SplitHostPort(dialAddr)
  335. if err != nil {
  336. rawConn.Close()
  337. return nil, errors.Trace(err)
  338. }
  339. selectedTLSProfile := config.TLSProfile
  340. if selectedTLSProfile == "" {
  341. selectedTLSProfile = SelectTLSProfile(false, false, "", p)
  342. }
  343. tlsConfigInsecureSkipVerify := false
  344. tlsConfigServerName := ""
  345. if config.SkipVerify {
  346. tlsConfigInsecureSkipVerify = true
  347. }
  348. if config.UseDialAddrSNI {
  349. tlsConfigServerName = hostname
  350. } else if config.SNIServerName != "" && config.VerifyLegacyCertificate == nil {
  351. // Set the ServerName and rely on the usual logic in
  352. // tls.Conn.Handshake() to do its verification.
  353. // Note: Go TLS will automatically omit this ServerName when it's an IP address
  354. tlsConfigServerName = config.SNIServerName
  355. } else {
  356. // No SNI.
  357. // Disable verification in tls.Conn.Handshake(). We'll verify manually
  358. // after handshaking
  359. tlsConfigInsecureSkipVerify = true
  360. }
  361. var tlsRootCAs *x509.CertPool
  362. if !config.SkipVerify &&
  363. config.VerifyLegacyCertificate == nil &&
  364. config.TrustedCACertificatesFilename != "" {
  365. tlsRootCAs = x509.NewCertPool()
  366. certData, err := ioutil.ReadFile(config.TrustedCACertificatesFilename)
  367. if err != nil {
  368. return nil, errors.Trace(err)
  369. }
  370. tlsRootCAs.AppendCertsFromPEM(certData)
  371. }
  372. tlsConfig := &utls.Config{
  373. RootCAs: tlsRootCAs,
  374. InsecureSkipVerify: tlsConfigInsecureSkipVerify,
  375. ServerName: tlsConfigServerName,
  376. }
  377. utlsClientHelloID, utlsClientHelloSpec, err := getUTLSClientHelloID(
  378. p, selectedTLSProfile)
  379. if err != nil {
  380. return nil, errors.Trace(err)
  381. }
  382. var randomizedTLSProfileSeed *prng.Seed
  383. isRandomized := protocol.TLSProfileIsRandomized(selectedTLSProfile)
  384. if isRandomized {
  385. randomizedTLSProfileSeed = config.RandomizedTLSProfileSeed
  386. if randomizedTLSProfileSeed == nil {
  387. randomizedTLSProfileSeed, err = prng.NewSeed()
  388. if err != nil {
  389. return nil, errors.Trace(err)
  390. }
  391. }
  392. utlsClientHelloID.Seed = new(utls.PRNGSeed)
  393. *utlsClientHelloID.Seed = [32]byte(*randomizedTLSProfileSeed)
  394. }
  395. // As noted here,
  396. // https://gitlab.com/yawning/obfs4/commit/ca6765e3e3995144df2b1ca9f0e9d823a7f8a47c,
  397. // the dynamic record sizing optimization in crypto/tls is not commonly
  398. // implemented in browsers. Disable it for all utls parrots and select it
  399. // randomly when using the randomized client hello.
  400. if isRandomized {
  401. PRNG, err := prng.NewPRNGWithSaltedSeed(randomizedTLSProfileSeed, "tls-dynamic-record-sizing")
  402. if err != nil {
  403. return nil, errors.Trace(err)
  404. }
  405. tlsConfig.DynamicRecordSizingDisabled = PRNG.FlipCoin()
  406. } else {
  407. tlsConfig.DynamicRecordSizingDisabled = true
  408. }
  409. conn := utls.UClient(rawConn, tlsConfig, utlsClientHelloID)
  410. if utlsClientHelloSpec != nil {
  411. err := conn.ApplyPreset(utlsClientHelloSpec)
  412. if err != nil {
  413. return nil, errors.Trace(err)
  414. }
  415. }
  416. clientSessionCache := config.clientSessionCache
  417. if clientSessionCache == nil {
  418. clientSessionCache = utls.NewLRUClientSessionCache(0)
  419. }
  420. conn.SetSessionCache(clientSessionCache)
  421. // TODO: can conn.SetClientRandom be made to take effect if called here? In
  422. // testing, the random value appears to be overwritten. As is, the overhead
  423. // of needRemarshal is now always required to handle
  424. // config.PassthroughMessage.
  425. // Build handshake state in advance to obtain the TLS version, which is used
  426. // to determine whether the following customizations may be applied. Don't use
  427. // getClientHelloVersion, since that may incur additional overhead.
  428. err = conn.BuildHandshakeState()
  429. if err != nil {
  430. return nil, errors.Trace(err)
  431. }
  432. isTLS13 := false
  433. for _, vers := range conn.HandshakeState.Hello.SupportedVersions {
  434. if vers == utls.VersionTLS13 {
  435. isTLS13 = true
  436. break
  437. }
  438. }
  439. // Add the obfuscated session ticket only when using TLS 1.2.
  440. //
  441. // Obfuscated session tickets are not currently supported in TLS 1.3, but we
  442. // allow UNFRONTED-MEEK-SESSION-TICKET-OSSH to use TLS 1.3 profiles for
  443. // additional diversity/capacity; TLS 1.3 encrypts the server certificate,
  444. // so the desired obfuscated session tickets property of obfuscating server
  445. // certificates is satisfied. We know that when the ClientHello offers TLS
  446. // 1.3, the Psiphon server, in these direct protocol cases, will negotiate
  447. // it.
  448. if config.ObfuscatedSessionTicketKey != "" && !isTLS13 {
  449. var obfuscatedSessionTicketKey [32]byte
  450. key, err := hex.DecodeString(config.ObfuscatedSessionTicketKey)
  451. if err == nil && len(key) != 32 {
  452. err = std_errors.New("invalid obfuscated session key length")
  453. }
  454. if err != nil {
  455. return nil, errors.Trace(err)
  456. }
  457. copy(obfuscatedSessionTicketKey[:], key)
  458. obfuscatedSessionState, err := tris.NewObfuscatedClientSessionState(
  459. obfuscatedSessionTicketKey)
  460. if err != nil {
  461. return nil, errors.Trace(err)
  462. }
  463. conn.SetSessionState(
  464. utls.MakeClientSessionState(
  465. obfuscatedSessionState.SessionTicket,
  466. obfuscatedSessionState.Vers,
  467. obfuscatedSessionState.CipherSuite,
  468. obfuscatedSessionState.MasterSecret,
  469. nil,
  470. nil))
  471. // Apply changes to utls
  472. err = conn.BuildHandshakeState()
  473. if err != nil {
  474. return nil, errors.Trace(err)
  475. }
  476. // Ensure that TLS ClientHello has required session ticket extension and
  477. // obfuscated session ticket cipher suite; the latter is required by
  478. // utls/tls.Conn.loadSession. If these requirements are not met the
  479. // obfuscation session ticket would be ignored, so fail.
  480. if !tris.ContainsObfuscatedSessionTicketCipherSuite(
  481. conn.HandshakeState.Hello.CipherSuites) {
  482. return nil, errors.TraceNew(
  483. "missing obfuscated session ticket cipher suite")
  484. }
  485. if len(conn.HandshakeState.Hello.SessionTicket) == 0 {
  486. return nil, errors.TraceNew("missing session ticket extension")
  487. }
  488. }
  489. // Perform at most one remarshal for the following ClientHello
  490. // modifications.
  491. needRemarshal := false
  492. // Either pre-TLS 1.3 ClientHellos or any randomized ClientHello is a
  493. // candidate for NoDefaultSessionID logic.
  494. if len(conn.HandshakeState.Hello.SessionTicket) == 0 &&
  495. (!isTLS13 || utlsClientHelloID.Client == "Randomized") {
  496. var noDefaultSessionID bool
  497. if config.NoDefaultTLSSessionID != nil {
  498. noDefaultSessionID = *config.NoDefaultTLSSessionID
  499. } else {
  500. noDefaultSessionID = config.ClientParameters.Get().WeightedCoinFlip(
  501. parameters.NoDefaultTLSSessionIDProbability)
  502. }
  503. if noDefaultSessionID {
  504. conn.HandshakeState.Hello.SessionId = nil
  505. needRemarshal = true
  506. }
  507. }
  508. // utls doesn't omit the server_name extension when the SNI value is empty
  509. // (including both the case where we set the SNI value to "" and the case
  510. // where the SNI address is an IP address, which is internally changed to
  511. // ""). To avoid a fingerprintable invalid/unusual server_name extension,
  512. // remove it in these cases.
  513. if tlsConfigServerName == "" || net.ParseIP(tlsConfigServerName) != nil {
  514. // Assumes only one SNIExtension.
  515. deleteIndex := -1
  516. for index, extension := range conn.Extensions {
  517. if _, ok := extension.(*utls.SNIExtension); ok {
  518. deleteIndex = index
  519. break
  520. }
  521. }
  522. if deleteIndex != -1 {
  523. conn.Extensions = append(
  524. conn.Extensions[:deleteIndex], conn.Extensions[deleteIndex+1:]...)
  525. }
  526. needRemarshal = true
  527. }
  528. if config.TLSPadding > 0 {
  529. tlsPadding := config.TLSPadding
  530. // Maximum padding size per RFC 7685
  531. if tlsPadding > 65535 {
  532. tlsPadding = 65535
  533. }
  534. // Assumes only one PaddingExtension.
  535. deleteIndex := -1
  536. for index, extension := range conn.Extensions {
  537. if _, ok := extension.(*utls.UtlsPaddingExtension); ok {
  538. deleteIndex = index
  539. break
  540. }
  541. }
  542. if deleteIndex != -1 {
  543. conn.Extensions = append(
  544. conn.Extensions[:deleteIndex], conn.Extensions[deleteIndex+1:]...)
  545. }
  546. paddingExtension := &utls.UtlsPaddingExtension{
  547. PaddingLen: tlsPadding,
  548. WillPad: true,
  549. }
  550. conn.Extensions = append([]utls.TLSExtension{paddingExtension}, conn.Extensions...)
  551. needRemarshal = true
  552. }
  553. if config.PassthroughMessage != nil {
  554. err := conn.SetClientRandom(config.PassthroughMessage)
  555. if err != nil {
  556. return nil, errors.Trace(err)
  557. }
  558. needRemarshal = true
  559. }
  560. if needRemarshal {
  561. // Apply changes to utls
  562. err = conn.MarshalClientHello()
  563. if err != nil {
  564. return nil, errors.Trace(err)
  565. }
  566. }
  567. // Perform the TLS Handshake.
  568. resultChannel := make(chan error)
  569. go func() {
  570. resultChannel <- conn.Handshake()
  571. }()
  572. select {
  573. case err = <-resultChannel:
  574. case <-ctx.Done():
  575. err = ctx.Err()
  576. // Interrupt the goroutine
  577. rawConn.Close()
  578. <-resultChannel
  579. }
  580. if err == nil && !config.SkipVerify && tlsConfigInsecureSkipVerify {
  581. if config.VerifyLegacyCertificate != nil {
  582. err = verifyLegacyCertificate(conn, config.VerifyLegacyCertificate)
  583. } else {
  584. // Manually verify certificates
  585. err = verifyServerCerts(conn, hostname)
  586. }
  587. }
  588. if err != nil {
  589. rawConn.Close()
  590. return nil, errors.Trace(err)
  591. }
  592. return conn, nil
  593. }
  594. func verifyLegacyCertificate(conn *utls.UConn, expectedCertificate *x509.Certificate) error {
  595. certs := conn.ConnectionState().PeerCertificates
  596. if len(certs) < 1 {
  597. return errors.TraceNew("no certificate to verify")
  598. }
  599. if !bytes.Equal(certs[0].Raw, expectedCertificate.Raw) {
  600. return errors.TraceNew("unexpected certificate")
  601. }
  602. return nil
  603. }
  604. func verifyServerCerts(conn *utls.UConn, hostname string) error {
  605. certs := conn.ConnectionState().PeerCertificates
  606. opts := x509.VerifyOptions{
  607. Roots: nil, // Use host's root CAs
  608. CurrentTime: time.Now(),
  609. DNSName: hostname,
  610. Intermediates: x509.NewCertPool(),
  611. }
  612. for i, cert := range certs {
  613. if i == 0 {
  614. continue
  615. }
  616. opts.Intermediates.AddCert(cert)
  617. }
  618. _, err := certs[0].Verify(opts)
  619. if err != nil {
  620. return errors.Trace(err)
  621. }
  622. return nil
  623. }
  624. func init() {
  625. // Favor compatibility over security. CustomTLSDial is used as an obfuscation
  626. // layer; users of CustomTLSDial, including meek and remote server list
  627. // downloads, don't depend on this TLS for its security properties.
  628. utls.EnableWeakCiphers()
  629. }