diff --git a/lib/service/service.go b/lib/service/service.go index 110e32c3c20b9..7dc53b47e3a3a 100644 --- a/lib/service/service.go +++ b/lib/service/service.go @@ -104,6 +104,7 @@ import ( "github.com/gravitational/teleport/lib/srv" "github.com/gravitational/teleport/lib/srv/alpnproxy" alpnproxyauth "github.com/gravitational/teleport/lib/srv/alpnproxy/auth" + "github.com/gravitational/teleport/lib/srv/alpnproxy/common" alpncommon "github.com/gravitational/teleport/lib/srv/alpnproxy/common" "github.com/gravitational/teleport/lib/srv/app" "github.com/gravitational/teleport/lib/srv/db" @@ -4108,10 +4109,19 @@ func (process *TeleportProcess) setupProxyTLSConfig(conn *Connector, tsrv revers if acmeCfg.URI != "" { m.Client = &acme.Client{DirectoryURL: acmeCfg.URI} } - tlsConfig = m.TLSConfig() + // We have to duplicate the behavior of `m.TLSConfig()` here because + // http/1.1 needs to take precedence over h2 due to + // https://bugs.chromium.org/p/chromium/issues/detail?id=1379017#c5 in Chrome. + tlsConfig = &tls.Config{ + GetCertificate: m.GetCertificate, + NextProtos: []string{ + string(common.ProtocolHTTP), string(common.ProtocolHTTP2), // enable HTTP/2 + acme.ALPNProto, // enable tls-alpn ACME challenges + }, + } utils.SetupTLSConfig(tlsConfig, cfg.CipherSuites) - tlsConfig.NextProtos = apiutils.Deduplicate(append(tlsConfig.NextProtos, acme.ALPNProto)) + tlsConfig.NextProtos = apiutils.Deduplicate(tlsConfig.NextProtos) } for _, pair := range process.Config.Proxy.KeyPairs { diff --git a/lib/service/service_test.go b/lib/service/service_test.go index 4c007ad8cc758..75fd66b6bbc03 100644 --- a/lib/service/service_test.go +++ b/lib/service/service_test.go @@ -491,9 +491,9 @@ func TestSetupProxyTLSConfig(t *testing.T) { name: "ACME enabled, teleport ALPN protocols should be appended", acmeEnabled: true, wantNextProtos: []string{ - // Ensure h2 has precedence over http/1.1. - "h2", + // Ensure http/1.1 has precedence over http2. "http/1.1", + "h2", "acme-tls/1", "teleport-postgres-ping", "teleport-mysql-ping", @@ -526,9 +526,9 @@ func TestSetupProxyTLSConfig(t *testing.T) { "teleport-sqlserver-ping", "teleport-snowflake-ping", "teleport-elasticsearch-ping", - // Ensure h2 has precedence over http/1.1. - "h2", + // Ensure http/1.1 has precedence over http2. "http/1.1", + "h2", "teleport-proxy-ssh", "teleport-reversetunnel", "teleport-auth@", diff --git a/lib/srv/alpnproxy/common/protocols.go b/lib/srv/alpnproxy/common/protocols.go index 8d3f0abccd05f..ac15b6929295b 100644 --- a/lib/srv/alpnproxy/common/protocols.go +++ b/lib/srv/alpnproxy/common/protocols.go @@ -62,7 +62,6 @@ const ( // be included in the list of ALPN header for the proxy server to handle the connection properly. ProtocolReverseTunnelV2 Protocol = "teleport-reversetunnelv2" - // ProtocolHTTP is TLS ALPN protocol value used to indicate HTTP2 protocol // ProtocolHTTP is TLS ALPN protocol value used to indicate HTTP 1.1 protocol ProtocolHTTP Protocol = "http/1.1" @@ -95,8 +94,14 @@ const ( var SupportedProtocols = append( ProtocolsWithPing(ProtocolsWithPingSupport...), append([]Protocol{ - ProtocolHTTP2, + // HTTP needs to be prioritized over HTTP2 due to a bug in Chrome: + // https://bugs.chromium.org/p/chromium/issues/detail?id=1379017 + // If Chrome resolves this, we can switch the prioritization. We may + // also be able to get around this if https://github.com/golang/go/issues/49918 + // is implemented and we can enable HTTP2 websockets on our end, but + // it's less clear to that fix will work. ProtocolHTTP, + ProtocolHTTP2, ProtocolProxySSH, ProtocolReverseTunnel, ProtocolAuth,