opensslConn.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // +build android windows
  2. /*
  3. * Copyright (c) 2015, Psiphon Inc.
  4. * All rights reserved.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. package psiphon
  21. import (
  22. "errors"
  23. "net"
  24. "strings"
  25. "github.com/Psiphon-Inc/openssl"
  26. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
  27. )
  28. // newOpenSSLConn wraps a connection with TLS which mimicks stock Android TLS.
  29. // This facility is used as a circumvention measure to ensure Psiphon client
  30. // TLS ClientHello messages match common TLS ClientHellos vs. the more
  31. // distinguishable (blockable) Go TLS ClientHello.
  32. func newOpenSSLConn(rawConn net.Conn, hostname string, config *CustomTLSConfig) (handshakeConn, error) {
  33. ctx, err := openssl.NewCtx()
  34. if err != nil {
  35. return nil, common.ContextError(err)
  36. }
  37. if !config.SkipVerify {
  38. ctx.SetVerifyMode(openssl.VerifyPeer)
  39. if config.VerifyLegacyCertificate != nil {
  40. // TODO: verify with VerifyLegacyCertificate
  41. return nil, errors.New("newOpenSSLConn does not support VerifyLegacyCertificate")
  42. } else {
  43. if config.TrustedCACertificatesFilename == "" {
  44. return nil, errors.New("newOpenSSLConn cannot verify without TrustedCACertificatesFilename")
  45. }
  46. err = ctx.LoadVerifyLocations(config.TrustedCACertificatesFilename, "")
  47. if err != nil {
  48. return nil, common.ContextError(err)
  49. }
  50. }
  51. } else {
  52. ctx.SetVerifyMode(openssl.VerifyNone)
  53. }
  54. // Use the same cipher suites, in the same priority order, as stock Android TLS.
  55. // Based on: https://android.googlesource.com/platform/external/conscrypt/+/master/src/main/java/org/conscrypt/NativeCrypto.java
  56. // This list includes include recently retired DSS suites: https://android.googlesource.com/platform/external/conscrypt/+/e53baea9221be7f9828d0f338ede284e22f55722%5E!/#F0,
  57. // as those are still commonly deployed.
  58. ciphersuites := []string{
  59. "ECDHE-ECDSA-AES128-GCM-SHA256",
  60. "ECDHE-ECDSA-AES256-GCM-SHA384",
  61. "ECDHE-RSA-AES128-GCM-SHA256",
  62. "ECDHE-RSA-AES256-GCM-SHA384",
  63. "DHE-RSA-AES128-GCM-SHA256",
  64. "DHE-RSA-AES256-GCM-SHA384",
  65. "ECDHE-ECDSA-AES128-SHA",
  66. "ECDHE-ECDSA-AES256-SHA",
  67. "ECDHE-RSA-AES128-SHA",
  68. "ECDHE-RSA-AES256-SHA",
  69. "DHE-RSA-AES128-SHA",
  70. "DHE-RSA-AES256-SHA",
  71. "DHE-DSS-AES128-SHA",
  72. "DHE-DSS-AES256-SHA",
  73. "ECDHE-ECDSA-RC4-SHA",
  74. "ECDHE-RSA-RC4-SHA",
  75. "AES128-GCM-SHA256",
  76. "AES256-GCM-SHA384",
  77. "AES128-SHA",
  78. "AES256-SHA",
  79. "RC4-SHA",
  80. }
  81. ctx.SetCipherList(strings.Join(ciphersuites, ":"))
  82. // Mimic extensions used by stock Android.
  83. // NOTE: Heartbeat extension is disabled at compile time.
  84. ctx.SetOptions(openssl.NoSessionResumptionOrRenegotiation | openssl.NoTicket)
  85. conn, err := openssl.Client(rawConn, ctx)
  86. if err != nil {
  87. return nil, common.ContextError(err)
  88. }
  89. if config.SNIServerName != "" {
  90. // Explicitly exclude IPs:
  91. // - "Literal IPv4 and IPv6 addresses are not permitted": https://tools.ietf.org/html/rfc6066#page-6.
  92. // - OpenSSL does not appear to enforce this rule itself.
  93. if net.ParseIP(config.SNIServerName) == nil {
  94. err = conn.SetTlsExtHostName(config.SNIServerName)
  95. if err != nil {
  96. return nil, common.ContextError(err)
  97. }
  98. }
  99. }
  100. return conn, nil
  101. }