aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCecylia Bocovich <cohosh@torproject.org>2023-06-12 20:34:41 -0400
committerCecylia Bocovich <cohosh@torproject.org>2023-06-14 18:12:29 -0400
commitf8eb86f24d659f8d41dc67bd12bf496dbd35c0b5 (patch)
treec09eea855109218552faab252b47a02991842b5a
parent9edaee65470a1483bbdbe984e5e15a885f1e95d2 (diff)
downloadsnowflake-f8eb86f24d659f8d41dc67bd12bf496dbd35c0b5.tar.gz
snowflake-f8eb86f24d659f8d41dc67bd12bf496dbd35c0b5.zip
Append Let's Encrypt ISRG Root X1 to cert pool
This is a workaround for older versions of android that do not trust the Let's Encrypt root certificate. https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/issues/40087
-rw-r--r--client/lib/rendezvous.go11
-rw-r--r--common/certs/certs.go54
2 files changed, 63 insertions, 2 deletions
diff --git a/client/lib/rendezvous.go b/client/lib/rendezvous.go
index ef0bf29..eeb4638 100644
--- a/client/lib/rendezvous.go
+++ b/client/lib/rendezvous.go
@@ -4,6 +4,7 @@
package snowflake_client
import (
+ "crypto/tls"
"errors"
"fmt"
@@ -14,6 +15,7 @@ import (
"github.com/pion/webrtc/v3"
utls "github.com/refraction-networking/utls"
+ "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/certs"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/event"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/messages"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/nat"
@@ -50,7 +52,10 @@ type BrokerChannel struct {
// and TLSHandshakeTimeout settings. But we want to disable the default
// ProxyFromEnvironment setting.
func createBrokerTransport() http.RoundTripper {
- transport := http.DefaultTransport.(*http.Transport)
+ tlsConfig := &tls.Config{
+ RootCAs: certs.GetRootCAs(),
+ }
+ transport := &http.Transport{TLSClientConfig: tlsConfig}
transport.Proxy = nil
transport.ResponseHeaderTimeout = 15 * time.Second
return transport
@@ -70,7 +75,9 @@ func newBrokerChannelFromConfig(config ClientConfig) (*BrokerChannel, error) {
if err != nil {
return nil, fmt.Errorf("unable to create broker channel: %v", err)
}
- utlsConfig := &utls.Config{}
+ utlsConfig := &utls.Config{
+ RootCAs: certs.GetRootCAs(),
+ }
brokerTransport = utlsutil.NewUTLSHTTPRoundTripper(utlsClientHelloID, utlsConfig, brokerTransport, config.UTLSRemoveSNI)
}
diff --git a/common/certs/certs.go b/common/certs/certs.go
new file mode 100644
index 0000000..11cb082
--- /dev/null
+++ b/common/certs/certs.go
@@ -0,0 +1,54 @@
+package certs
+
+import (
+ "crypto/x509"
+ "log"
+)
+
+// https://crt.sh/?id=3958242236
+const LetsEncryptRootCert = `-----BEGIN CERTIFICATE-----
+MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/
+MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
+DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow
+TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
+cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XC
+ov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpL
+wYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+D
+LtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK
+4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5
+bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5y
+sR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZ
+Xmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4
+FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBc
+SLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2ql
+PRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TND
+TwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
+SwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1
+c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx
++tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEB
+ATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQu
+b3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9E
+U1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26Ztu
+MA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC
+5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW
+9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuG
+WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O
+he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC
+Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5
+-----END CERTIFICATE-----`
+
+// GetRootCAs is a workaround for older versions of Android that do not trust
+// Let's Encrypt's ISRG Root X1. This manually adds the ISRG root to the device's
+// existing cert pool.
+func GetRootCAs() *x509.CertPool {
+ rootCerts, err := x509.SystemCertPool()
+ if err != nil {
+ rootCerts = x509.NewCertPool()
+ }
+ if ok := rootCerts.AppendCertsFromPEM([]byte(LetsEncryptRootCert)); !ok {
+ log.Println("Error appending Let's Encrypt root certificate to cert poool")
+ return nil
+ }
+ return rootCerts
+}