From f8eb86f24d659f8d41dc67bd12bf496dbd35c0b5 Mon Sep 17 00:00:00 2001 From: Cecylia Bocovich Date: Mon, 12 Jun 2023 20:34:41 -0400 Subject: [PATCH] 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 --- client/lib/rendezvous.go | 11 ++++++-- common/certs/certs.go | 54 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 common/certs/certs.go 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 +}