Browse Source

Further strip unique signatures of tls handshake

1. allow users to disable session ticket
2. set default alpn to ["h2", "http/1.1"]
Darhwa 5 years ago
parent
commit
8e791e92bc

+ 1 - 1
app/proxyman/outbound/handler.go

@@ -144,7 +144,7 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (internet.Conn
 				conn := net.NewConnection(net.ConnectionInputMulti(uplinkWriter), net.ConnectionOutputMulti(downlinkReader))
 
 				if config := tls.ConfigFromStreamSettings(h.streamSettings); config != nil {
-					tlsConfig := config.GetTLSConfig(tls.WithDestination(dest), tls.WithNextProto("h2"))
+					tlsConfig := config.GetTLSConfig(tls.WithDestination(dest))
 					conn = tls.Client(conn, tlsConfig)
 				}
 

+ 9 - 7
infra/conf/transport_internet.go

@@ -274,12 +274,13 @@ func (c *TLSCertConfig) Build() (*tls.Certificate, error) {
 }
 
 type TLSConfig struct {
-	Insecure         bool             `json:"allowInsecure"`
-	InsecureCiphers  bool             `json:"allowInsecureCiphers"`
-	Certs            []*TLSCertConfig `json:"certificates"`
-	ServerName       string           `json:"serverName"`
-	ALPN             *StringList      `json:"alpn"`
-	DiableSystemRoot bool             `json:"disableSystemRoot"`
+	Insecure                 bool             `json:"allowInsecure"`
+	InsecureCiphers          bool             `json:"allowInsecureCiphers"`
+	Certs                    []*TLSCertConfig `json:"certificates"`
+	ServerName               string           `json:"serverName"`
+	ALPN                     *StringList      `json:"alpn"`
+	DisableSessionResumption bool             `json:"disableSessionResumption"`
+	DisableSystemRoot        bool             `json:"disableSystemRoot"`
 }
 
 // Build implements Buildable.
@@ -302,7 +303,8 @@ func (c *TLSConfig) Build() (proto.Message, error) {
 	if c.ALPN != nil && len(*c.ALPN) > 0 {
 		config.NextProtocol = []string(*c.ALPN)
 	}
-	config.DisableSystemRoot = c.DiableSystemRoot
+	config.DisableSessionResumption = c.DisableSessionResumption
+	config.DisableSystemRoot = c.DisableSystemRoot
 	return config, nil
 }
 

+ 22 - 5
transport/internet/http/dialer.go

@@ -20,12 +20,12 @@ import (
 
 var (
 	globalDialerMap    map[net.Destination]*http.Client
-	globalDailerAccess sync.Mutex
+	globalDialerAccess sync.Mutex
 )
 
 func getHTTPClient(ctx context.Context, dest net.Destination, tlsSettings *tls.Config) (*http.Client, error) {
-	globalDailerAccess.Lock()
-	defer globalDailerAccess.Unlock()
+	globalDialerAccess.Lock()
+	defer globalDialerAccess.Unlock()
 
 	if globalDialerMap == nil {
 		globalDialerMap = make(map[net.Destination]*http.Client)
@@ -54,9 +54,26 @@ func getHTTPClient(ctx context.Context, dest net.Destination, tlsSettings *tls.C
 			if err != nil {
 				return nil, err
 			}
-			return gotls.Client(pconn, tlsConfig), nil
+
+			cn := gotls.Client(pconn, tlsConfig)
+			if err := cn.Handshake(); err != nil {
+				return nil, err
+			}
+			if !tlsConfig.InsecureSkipVerify {
+				if err := cn.VerifyHostname(tlsConfig.ServerName); err != nil {
+					return nil, err
+				}
+			}
+			state := cn.ConnectionState()
+			if p := state.NegotiatedProtocol; p != http2.NextProtoTLS {
+				return nil, newError("http2: unexpected ALPN protocol " + p + "; want q" + http2.NextProtoTLS).AtError()
+			}
+			if !state.NegotiatedProtocolIsMutual {
+				return nil, newError("http2: could not negotiate protocol mutually").AtError()
+			}
+			return cn, nil
 		},
-		TLSClientConfig: tlsSettings.GetTLSConfig(tls.WithDestination(dest), tls.WithNextProto("h2")),
+		TLSClientConfig: tlsSettings.GetTLSConfig(tls.WithDestination(dest)),
 	}
 
 	client := &http.Client{

+ 1 - 1
transport/internet/tcp/dialer.go

@@ -21,7 +21,7 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
 	}
 
 	if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
-		tlsConfig := config.GetTLSConfig(tls.WithDestination(dest), tls.WithNextProto("h2"))
+		tlsConfig := config.GetTLSConfig(tls.WithDestination(dest))
 		if config.IsExperiment8357() {
 			conn = tls.UClient(conn, tlsConfig)
 		} else {

+ 3 - 10
transport/internet/tls/config.go

@@ -176,6 +176,8 @@ func (c *Config) GetTLSConfig(opts ...Option) *tls.Config {
 	config := &tls.Config{
 		ClientSessionCache:     globalSessionCache,
 		RootCAs:                root,
+		InsecureSkipVerify:     c.AllowInsecure,
+		NextProtos:             c.NextProtocol,
 		SessionTicketsDisabled: c.DisableSessionResumption,
 	}
 	if c == nil {
@@ -186,12 +188,6 @@ func (c *Config) GetTLSConfig(opts ...Option) *tls.Config {
 		opt(config)
 	}
 
-	if !c.AllowInsecureCiphers && len(config.CipherSuites) == 0 {
-		// crypto/tls will use the proper ciphers
-		config.CipherSuites = nil
-	}
-
-	config.InsecureSkipVerify = c.AllowInsecure
 	config.Certificates = c.BuildCertificates()
 	config.BuildNameToCertificate()
 
@@ -204,11 +200,8 @@ func (c *Config) GetTLSConfig(opts ...Option) *tls.Config {
 		config.ServerName = sn
 	}
 
-	if len(c.NextProtocol) > 0 {
-		config.NextProtos = c.NextProtocol
-	}
 	if len(config.NextProtos) == 0 {
-		config.NextProtos = []string{"http/1.1"}
+		config.NextProtos = []string{"h2", "http/1.1"}
 	}
 
 	return config

+ 1 - 1
transport/internet/websocket/dialer.go

@@ -45,7 +45,7 @@ func dialWebsocket(ctx context.Context, dest net.Destination, streamSettings *in
 
 	if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
 		protocol = "wss"
-		dialer.TLSClientConfig = config.GetTLSConfig(tls.WithDestination(dest))
+		dialer.TLSClientConfig = config.GetTLSConfig(tls.WithDestination(dest), tls.WithNextProto("http/1.1"))
 	}
 
 	host := dest.NetAddr()