Jelajahi Sumber

Simplify TLS config

- Remove UseIndistinguishableTLS, and always
  use utls.

- Remove UseTrustedCACertificatesForStockTLS
  and use TrustedCACertificatesFilename as
  the flag as well as filename value.

  TrustedCACertificatesFilename is no longer
  used for OpenSSL, so the case where
  UseTrustedCACertificatesForStockTLS is set
  is now the _only_ case where
  TrustedCACertificatesFilename is used.

- Add explicit error when TrustedCACertificatesFilename
  is set, CA certs are rewuired, but the
  TrustedCACertificatesFilename certs cannot
  be used. This case is _not_ expected to occur
  in practise, but now has an explicit error
  that will be reported if that changes.
Rod Hynes 7 tahun lalu
induk
melakukan
3b643542de

+ 7 - 13
MobileLibrary/Android/PsiphonTunnel/PsiphonTunnel.java

@@ -535,20 +535,14 @@ public class PsiphonTunnel extends Psi.PsiphonProvider.Stub {
             json.put("LocalSocksProxyPort", mLocalSocksProxyPort);
         }
 
-        json.put("UseIndistinguishableTLS", true);
-
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
-            json.put("UseTrustedCACertificatesForStockTLS", true);
-        }
-
-        try {
-            // Also enable indistinguishable TLS for HTTPS requests that
-            // require system CAs.
-            json.put(
-                    "TrustedCACertificatesFilename",
-                    setupTrustedCertificates(mHostService.getContext()));
-        } catch (Exception e) {
-            mHostService.onDiagnosticMessage(e.getMessage());
+            try {
+                json.put(
+                        "TrustedCACertificatesFilename",
+                        setupTrustedCertificates(mHostService.getContext()));
+            } catch (Exception e) {
+                mHostService.onDiagnosticMessage(e.getMessage());
+            }
         }
 
         json.put("DeviceRegion", getDeviceRegion(mHostService.getContext()));

+ 0 - 5
MobileLibrary/iOS/PsiphonTunnel/PsiphonTunnel/PsiphonTunnel.m

@@ -633,11 +633,6 @@
         
     config[@"DeviceRegion"] = [PsiphonTunnel getDeviceRegion];
     
-    config[@"UseIndistinguishableTLS"] = [NSNumber numberWithBool:TRUE];
-
-    // We don't use OpenSSL, so we don't use a CA certs file
-    config[@"TrustedCACertificatesFilename"] = nil;
-
     // This library expects a pool size of 1
     config[@"TunnelPoolSize"] = [NSNumber numberWithInt:1];
 

+ 6 - 14
psiphon/config.go

@@ -387,21 +387,13 @@ type Config struct {
 	// bytes sent and received.
 	EmitBytesTransferred bool
 
-	// UseIndistinguishableTLS enables use of alternative TLS profiles with a
-	// less distinct fingerprint (ClientHello content) than the stock Go TLS.
-	UseIndistinguishableTLS bool
-
-	// UseTrustedCACertificatesForStockTLS toggles use of the trusted CA
-	// certs, specified in TrustedCACertificatesFilename, for tunneled TLS
-	// connections that expect server certificates signed with public
-	// certificate authorities (currently, only upgrade downloads). This
-	// option is used with stock Go TLS in cases where Go may fail to obtain a
-	// list of root CAs from the operating system. Requires
-	// TrustedCACertificatesFilename to be set.
-	UseTrustedCACertificatesForStockTLS bool
-
 	// TrustedCACertificatesFilename specifies a file containing trusted CA
-	// certs.
+	// certs. When set, this toggles use of the trusted CA certs, specified in
+	// TrustedCACertificatesFilename, for tunneled TLS connections that expect
+	// server certificates signed with public certificate authorities
+	// (currently, only upgrade downloads). This option is used with stock Go
+	// TLS in cases where Go may fail to obtain a list of root CAs from the
+	// operating system.
 	TrustedCACertificatesFilename string
 
 	// DisablePeriodicSshKeepAlive indicates whether to send an SSH keepalive

+ 0 - 1
psiphon/controller.go

@@ -106,7 +106,6 @@ func NewController(config *Config) (controller *Controller, err error) {
 		DeviceBinder:                  config.deviceBinder,
 		DnsServerGetter:               config.DnsServerGetter,
 		IPv6Synthesizer:               config.IPv6Synthesizer,
-		UseIndistinguishableTLS:       config.UseIndistinguishableTLS,
 		TrustedCACertificatesFilename: config.TrustedCACertificatesFilename,
 	}
 

+ 0 - 1
psiphon/feedback.go

@@ -119,7 +119,6 @@ func SendFeedback(configJson, diagnosticsJson, b64EncodedPublicKey, uploadServer
 		DeviceBinder:                  nil,
 		IPv6Synthesizer:               nil,
 		DnsServerGetter:               nil,
-		UseIndistinguishableTLS:       config.UseIndistinguishableTLS,
 		TrustedCACertificatesFilename: config.TrustedCACertificatesFilename,
 	}
 

+ 0 - 3
psiphon/meekConn.go

@@ -80,8 +80,6 @@ type MeekConfig struct {
 	// TLSProfile specifies the TLS profile to use for all underlying
 	// TLS connections created by this meek connection. Valid values
 	// are the possible values for CustomTLSConfig.TLSProfile.
-	// TLSProfile will be used only when DialConfig.UseIndistinguishableTLS
-	// is set in the DialConfig passed in to DialMeek.
 	TLSProfile string
 
 	// UseObfuscatedSessionTickets indicates whether to use obfuscated
@@ -249,7 +247,6 @@ func DialMeek(
 			Dial:                          tcpDialer,
 			SNIServerName:                 meekConfig.SNIServerName,
 			SkipVerify:                    true,
-			UseIndistinguishableTLS:       dialConfig.UseIndistinguishableTLS,
 			TLSProfile:                    meekConfig.TLSProfile,
 			TrustedCACertificatesFilename: dialConfig.TrustedCACertificatesFilename,
 		}

+ 5 - 23
psiphon/net.go

@@ -73,16 +73,8 @@ type DialConfig struct {
 	DnsServerGetter DnsServerGetter
 	IPv6Synthesizer IPv6Synthesizer
 
-	// UseIndistinguishableTLS specifies whether to try to use an
-	// alternative stack for TLS. From a circumvention perspective,
-	// Go's TLS has a distinct fingerprint that may be used for blocking.
-	// Only applies to TLS connections.
-	UseIndistinguishableTLS bool
-
 	// TrustedCACertificatesFilename specifies a file containing trusted
-	// CA certs. The file contents should be compatible with OpenSSL's
-	// SSL_CTX_load_verify_locations.
-	// Only applies to UseIndistinguishableTLS connections.
+	// CA certs. See Config.TrustedCACertificatesFilename.
 	TrustedCACertificatesFilename string
 
 	// ResolvedIPCallback, when set, is called with the IP address that was
@@ -235,10 +227,9 @@ func ResolveIP(host string, conn net.Conn) (addrs []net.IP, ttls []time.Duration
 	return addrs, ttls, nil
 }
 
-// MakeUntunneledHTTPClient returns a net/http.Client which is
-// configured to use custom dialing features -- including BindToDevice,
-// UseIndistinguishableTLS, etc. If verifyLegacyCertificate is not nil,
-// it's used for certificate verification.
+// MakeUntunneledHTTPClient returns a net/http.Client which is configured to
+// use custom dialing features -- including BindToDevice, etc. If
+// verifyLegacyCertificate is not nil, it's used for certificate verification.
 // The context is applied to underlying TCP dials. The caller is responsible
 // for applying the context to requests made with the returned http.Client.
 func MakeUntunneledHTTPClient(
@@ -248,10 +239,6 @@ func MakeUntunneledHTTPClient(
 	verifyLegacyCertificate *x509.Certificate,
 	skipVerify bool) (*http.Client, error) {
 
-	// Note: IndistinguishableTLS mode doesn't support VerifyLegacyCertificate
-	useIndistinguishableTLS := untunneledDialConfig.UseIndistinguishableTLS &&
-		verifyLegacyCertificate == nil
-
 	dialer := NewTCPDialer(untunneledDialConfig)
 
 	tlsDialer := NewCustomTLSDialer(
@@ -264,7 +251,6 @@ func MakeUntunneledHTTPClient(
 			UseDialAddrSNI:                true,
 			SNIServerName:                 "",
 			SkipVerify:                    skipVerify,
-			UseIndistinguishableTLS:       useIndistinguishableTLS,
 			TrustedCACertificatesFilename: untunneledDialConfig.TrustedCACertificatesFilename,
 		})
 
@@ -308,12 +294,8 @@ func MakeTunneledHTTPClient(
 
 		transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
 
-	} else if config.UseTrustedCACertificatesForStockTLS {
+	} else if config.TrustedCACertificatesFilename != "" {
 
-		if config.TrustedCACertificatesFilename == "" {
-			return nil, common.ContextError(errors.New(
-				"UseTrustedCACertificatesForStockTLS requires TrustedCACertificatesFilename"))
-		}
 		rootCAs := x509.NewCertPool()
 		certData, err := ioutil.ReadFile(config.TrustedCACertificatesFilename)
 		if err != nil {

+ 1 - 2
psiphon/server/meek_test.go

@@ -296,8 +296,7 @@ func TestMeekResiliency(t *testing.T) {
 	// Run meek client
 
 	dialConfig := &psiphon.DialConfig{
-		UseIndistinguishableTLS: true,
-		DeviceBinder:            new(fileDescriptorInterruptor),
+		DeviceBinder: new(fileDescriptorInterruptor),
 	}
 
 	clientParameters, err := parameters.NewClientParameters(nil)

+ 0 - 1
psiphon/server/server_test.go

@@ -564,7 +564,6 @@ func runServer(t *testing.T, runConfig *runServerConfig) {
         "SponsorId" : "0",
         "PropagationChannelId" : "0",
         "DisableRemoteServerListFetcher" : true,
-        "UseIndistinguishableTLS" : true,
         "EstablishTunnelPausePeriodSeconds" : 1,
         "ConnectionWorkerPoolSize" : %d,
         "TunnelProtocols" : ["%s"]

+ 29 - 38
psiphon/tlsDialer.go

@@ -121,26 +121,17 @@ type CustomTLSConfig struct {
 	// specified certificate. SNI is disbled when this is set.
 	VerifyLegacyCertificate *x509.Certificate
 
-	// UseIndistinguishableTLS specifies whether to try to use an
-	// alternative profile for TLS dials. From a circumvention perspective,
-	// Go's TLS has a distinct fingerprint that may be used for blocking.
-	UseIndistinguishableTLS bool
-
-	// TLSProfile specifies a particular indistinguishable TLS profile
-	// to use for the TLS dial. UseIndistinguishableTLS must be set for
-	// TLSProfile to take effect.
-	// When TLSProfile is "" and UseIndistinguishableTLS is set, a profile
-	// is selected at random. Setting TLSProfile allows the caller to pin
-	// the selection so all TLS connections in a certain context (e.g. a
-	// single meek connection) use a consistent value.
-	// The value should be selected by calling SelectTLSProfile, which
-	// will pick a value at random, subject to compatibility constraints.
+	// TLSProfile specifies a particular indistinguishable TLS profile to use
+	// for the TLS dial. When TLSProfile is "", a profile is selected at
+	// random. Setting TLSProfile allows the caller to pin the selection so
+	// all TLS connections in a certain context (e.g. a single meek
+	// connection) use a consistent value. The value should be selected by
+	// calling SelectTLSProfile, which will pick a value at random, subject to
+	// compatibility constraints.
 	TLSProfile string
 
 	// TrustedCACertificatesFilename specifies a file containing trusted
-	// CA certs. Directory contents should be compatible with OpenSSL's
-	// SSL_CTX_load_verify_locations
-	// Only applies to UseIndistinguishableTLS connections.
+	// CA certs. See Config.TrustedCACertificatesFilename.
 	TrustedCACertificatesFilename string
 
 	// ObfuscatedSessionTicketKey enables obfuscated session tickets
@@ -149,36 +140,30 @@ type CustomTLSConfig struct {
 }
 
 func SelectTLSProfile(
-	useIndistinguishableTLS bool,
 	tunnelProtocol string,
 	clientParameters *parameters.ClientParameters) string {
 
-	if useIndistinguishableTLS {
+	limitTLSProfiles := clientParameters.Get().TLSProfiles(parameters.LimitTLSProfiles)
 
-		limitTLSProfiles := clientParameters.Get().TLSProfiles(parameters.LimitTLSProfiles)
+	tlsProfiles := make([]string, 0)
 
-		tlsProfiles := make([]string, 0)
+	for _, tlsProfile := range protocol.SupportedTLSProfiles {
 
-		for _, tlsProfile := range protocol.SupportedTLSProfiles {
-
-			if len(limitTLSProfiles) > 0 &&
-				!common.Contains(limitTLSProfiles, tlsProfile) {
-				continue
-			}
-
-			tlsProfiles = append(tlsProfiles, tlsProfile)
-		}
-
-		if len(tlsProfiles) == 0 {
-			return ""
+		if len(limitTLSProfiles) > 0 &&
+			!common.Contains(limitTLSProfiles, tlsProfile) {
+			continue
 		}
 
-		choice, _ := common.MakeSecureRandomInt(len(tlsProfiles))
+		tlsProfiles = append(tlsProfiles, tlsProfile)
+	}
 
-		return tlsProfiles[choice]
+	if len(tlsProfiles) == 0 {
+		return ""
 	}
 
-	return ""
+	choice, _ := common.MakeSecureRandomInt(len(tlsProfiles))
+
+	return tlsProfiles[choice]
 }
 
 func getClientHelloID(tlsProfile string) utls.ClientHelloID {
@@ -223,6 +208,13 @@ func CustomTLSDial(
 	network, addr string,
 	config *CustomTLSConfig) (net.Conn, error) {
 
+	if !config.SkipVerify &&
+		config.VerifyLegacyCertificate == nil &&
+		config.TrustedCACertificatesFilename != "" {
+		return nil, common.ContextError(
+			errors.New("TrustedCACertificatesFilename not supported"))
+	}
+
 	dialAddr := addr
 	if config.DialAddr != "" {
 		dialAddr = config.DialAddr
@@ -242,8 +234,7 @@ func CustomTLSDial(
 	selectedTLSProfile := config.TLSProfile
 
 	if selectedTLSProfile == "" {
-		selectedTLSProfile = SelectTLSProfile(
-			config.UseIndistinguishableTLS, "", config.ClientParameters)
+		selectedTLSProfile = SelectTLSProfile("", config.ClientParameters)
 	}
 
 	tlsConfig := &utls.Config{

+ 0 - 2
psiphon/tunnel.go

@@ -721,7 +721,6 @@ func initMeekConfig(
 	selectedTLSProfile := ""
 	if protocol.TunnelProtocolUsesMeekHTTPS(selectedProtocol) {
 		selectedTLSProfile = SelectTLSProfile(
-			config.UseIndistinguishableTLS,
 			selectedProtocol,
 			config.clientParameters)
 	}
@@ -786,7 +785,6 @@ func initDialConfig(
 		DeviceBinder:                  config.deviceBinder,
 		DnsServerGetter:               config.DnsServerGetter,
 		IPv6Synthesizer:               config.IPv6Synthesizer,
-		UseIndistinguishableTLS:       config.UseIndistinguishableTLS,
 		TrustedCACertificatesFilename: config.TrustedCACertificatesFilename,
 	}