diff --git a/app/proxyman/outbound/handler.go b/app/proxyman/outbound/handler.go index eead10b7933..34ad6cc763f 100644 --- a/app/proxyman/outbound/handler.go +++ b/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) } diff --git a/infra/conf/transport_internet.go b/infra/conf/transport_internet.go index 740d7ee3e11..4cd604e7090 100644 --- a/infra/conf/transport_internet.go +++ b/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 } diff --git a/transport/internet/http/dialer.go b/transport/internet/http/dialer.go index 98187d95556..ffa727417b1 100644 --- a/transport/internet/http/dialer.go +++ b/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{ diff --git a/transport/internet/tcp/dialer.go b/transport/internet/tcp/dialer.go index 7c7d86c1a80..322583a4f0d 100644 --- a/transport/internet/tcp/dialer.go +++ b/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 { diff --git a/transport/internet/tls/config.go b/transport/internet/tls/config.go index 2cd25721ab0..32035c47a62 100644 --- a/transport/internet/tls/config.go +++ b/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 diff --git a/transport/internet/websocket/dialer.go b/transport/internet/websocket/dialer.go index 98b66d0188c..7545f8537d1 100644 --- a/transport/internet/websocket/dialer.go +++ b/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()