cmd/k8s-operator: disable HTTP/2 for the auth proxy

Kubernetes uses SPDY/3.1 which is incompatible with HTTP/2, disable it
in the transport and server.

Fixes #7645
Fixes #7646

Signed-off-by: Maisem Ali <maisem@tailscale.com>
This commit is contained in:
Maisem Ali 2023-03-23 11:37:26 -07:00 committed by Maisem Ali
parent 8a246487c2
commit df89b7de10
2 changed files with 32 additions and 5 deletions

View File

@ -7,8 +7,10 @@
import (
"context"
"crypto/tls"
_ "embed"
"fmt"
"net/http"
"os"
"strings"
"time"
@ -25,7 +27,7 @@
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/rest"
"k8s.io/client-go/transport"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
@ -235,9 +237,23 @@ func main() {
startlog.Infof("Startup complete, operator running")
if shouldRunAuthProxy {
rt, err := rest.TransportFor(restConfig)
cfg, err := restConfig.TransportConfig()
if err != nil {
startlog.Fatalf("could not get rest transport: %v", err)
startlog.Fatalf("could not get rest.TransportConfig(): %v", err)
}
// Kubernetes uses SPDY for exec and port-forward, however SPDY is
// incompatible with HTTP/2; so disable HTTP/2 in the proxy.
tr := http.DefaultTransport.(*http.Transport).Clone()
tr.TLSClientConfig, err = transport.TLSConfigFor(cfg)
if err != nil {
startlog.Fatalf("could not get transport.TLSConfigFor(): %v", err)
}
tr.TLSNextProto = make(map[string]func(authority string, c *tls.Conn) http.RoundTripper)
rt, err := transport.HTTPWrappersForConfig(cfg, tr)
if err != nil {
startlog.Fatalf("could not get rest.TransportConfig(): %v", err)
}
go runAuthProxy(s, rt, zlog.Named("auth-proxy").Infof)
}

View File

@ -5,6 +5,7 @@
import (
"context"
"crypto/tls"
"fmt"
"log"
"net/http"
@ -48,7 +49,7 @@ func (h *authProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
//
// It never returns.
func runAuthProxy(s *tsnet.Server, rt http.RoundTripper, logf logger.Logf) {
ln, err := s.ListenTLS("tcp", ":443")
ln, err := s.Listen("tcp", ":443")
if err != nil {
log.Fatalf("could not listen on :443: %v", err)
}
@ -103,7 +104,17 @@ func runAuthProxy(s *tsnet.Server, rt http.RoundTripper, logf logger.Logf) {
Transport: rt,
},
}
if err := http.Serve(ln, ap); err != nil {
hs := &http.Server{
// Kubernetes uses SPDY for exec and port-forward, however SPDY is
// incompatible with HTTP/2; so disable HTTP/2 in the proxy.
TLSConfig: &tls.Config{
GetCertificate: lc.GetCertificate,
NextProtos: []string{"http/1.1"},
},
TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler)),
Handler: ap,
}
if err := hs.ServeTLS(ln, "", ""); err != nil {
log.Fatalf("runAuthProxy: failed to serve %v", err)
}
}