Skip to content

Commit 12ff519

Browse files
simonpasquieradinhodovic
authored andcommitted
fix: disable HTTP2 connections by default
This change mitigates CVE-2023-44487 by disabling HTTP2 by default and forcing HTTP/1.1 until the Go standard library and golang.org/x/net are fully fixed. Right now, it is possible for authenticated and unauthenticated users to hold open HTTP2 connections and consume huge amounts of memory. It is possible to revert back the change by using the `--web.enable-http2` argument. Before this change: ``` curl -kv https://localhost:8443/metrics * Trying 127.0.0.1:8443... * Connected to localhost (127.0.0.1) port 8443 (#0) * ALPN: offers h2,http/1.1 [...] * ALPN: server accepted h2 [...] * using HTTP/2 * h2h3 [:method: GET] * h2h3 [:path: /metrics] * h2h3 [:scheme: https] * h2h3 [:authority: localhost:8443] * h2h3 [user-agent: curl/8.0.1] * h2h3 [accept: */*] * Using Stream ID: 1 (easy handle 0x5594d4614b10) [...] > GET /metrics HTTP/2 [...] ``` After this change: ``` curl -kv https://localhost:8443/metrics * Trying 127.0.0.1:8443... * Connected to localhost (127.0.0.1) port 8443 (#0) * ALPN: offers h2,http/1.1 [...] * ALPN: server accepted http/1.1 [...] * using HTTP/1.1 > GET /metrics HTTP/1.1 > Host: localhost:8443 > User-Agent: curl/8.0.1 > Accept: */* [...] < HTTP/1.1 200 OK [...] ``` See also: * kubernetes/kubernetes#121120 * kubernetes/kubernetes#121197 * golang/go#63417 (comment) Signed-off-by: Simon Pasquier <[email protected]>
1 parent c1aab65 commit 12ff519

File tree

3 files changed

+42
-12
lines changed

3 files changed

+42
-12
lines changed

Documentation/operator.md

+2
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ Usage of ./operator:
8989
Cert file to be used for operator web server endpoints. (default "/etc/tls/private/tls.crt")
9090
-web.client-ca-file string
9191
Client CA certificate file to be used for operator web server endpoints. (default "/etc/tls/private/tls-ca.crt")
92+
-web.enable-http2
93+
Enable HTTP2 connections.
9294
-web.enable-tls
9395
Activate prometheus operator web server TLS. This is useful for example when using the rule validation webhook.
9496
-web.key-file string

cmd/admission-webhook/main.go

+26-11
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,22 @@ var (
5353
cfg = config{}
5454
flagset = flag.CommandLine
5555

56+
enableHTTP2 bool
5657
serverTLS bool
5758
rawTLSCipherSuites string
5859
)
5960

6061
func main() {
6162
flagset.StringVar(&cfg.ListenAddress, "web.listen-address", ":8443", "Address on which the admission webhook service listens")
63+
// Mitigate CVE-2023-44487 by disabling HTTP2 by default until the Go
64+
// standard library and golang.org/x/net are fully fixed.
65+
// Right now, it is possible for authenticated and unauthenticated users to
66+
// hold open HTTP2 connections and consume huge amounts of memory.
67+
// See:
68+
// * https://github.com/kubernetes/kubernetes/pull/121120
69+
// * https://github.com/kubernetes/kubernetes/issues/121197
70+
// * https://github.com/golang/go/issues/63417#issuecomment-1758858612
71+
flagset.BoolVar(&enableHTTP2, "web.enable-http2", false, "Enable HTTP2 connections.")
6272
flagset.BoolVar(&serverTLS, "web.enable-tls", true, "Enable TLS web server")
6373

6474
flagset.StringVar(&cfg.ServerTLSConfig.CertFile, "web.cert-file", defaultCrtFile, "Certificate file to be used for the web server.")
@@ -127,7 +137,7 @@ func (s *srv) run(listener net.Listener) error {
127137
log := log.With(s.logger, "address", listener.Addr().String())
128138

129139
if s.s.TLSConfig != nil {
130-
level.Info(log).Log("msg", "Starting TLS enabled server")
140+
level.Info(log).Log("msg", "Starting TLS enabled server", "http2", enableHTTP2)
131141
if err := s.s.ServeTLS(listener, "", ""); err != http.ErrServerClosed {
132142
return err
133143
}
@@ -163,18 +173,23 @@ func newSrv(logger log.Logger, tlsConf *tls.Config) *srv {
163173
w.WriteHeader(http.StatusOK)
164174
})
165175

176+
httpServer := http.Server{
177+
Handler: mux,
178+
TLSConfig: tlsConf,
179+
ReadHeaderTimeout: 30 * time.Second,
180+
ReadTimeout: 30 * time.Second,
181+
// use flags on standard logger to align with base logger and get consistent parsed fields form adapter:
182+
// use shortfile flag to get proper 'caller' field (avoid being wrongly parsed/extracted from message)
183+
// and no datetime related flag to keep 'ts' field from base logger (with controlled format)
184+
ErrorLog: stdlog.New(log.NewStdlibAdapter(logger), "", stdlog.Lshortfile),
185+
}
186+
if !enableHTTP2 {
187+
httpServer.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler))
188+
}
189+
166190
return &srv{
167191
logger: logger,
168-
s: &http.Server{
169-
Handler: mux,
170-
TLSConfig: tlsConf,
171-
ReadHeaderTimeout: 30 * time.Second,
172-
ReadTimeout: 30 * time.Second,
173-
// use flags on standard logger to align with base logger and get consistent parsed fields form adapter:
174-
// use shortfile flag to get proper 'caller' field (avoid being wrongly parsed/extracted from message)
175-
// and no datetime related flag to keep 'ts' field from base logger (with controlled format)
176-
ErrorLog: stdlog.New(log.NewStdlibAdapter(logger), "", stdlog.Lshortfile),
177-
},
192+
s: &httpServer,
178193
}
179194
}
180195

cmd/operator/main.go

+14-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ func serve(srv *http.Server, listener net.Listener, logger log.Logger) func() er
144144

145145
func serveTLS(srv *http.Server, listener net.Listener, logger log.Logger) func() error {
146146
return func() error {
147-
level.Info(logger).Log("msg", "Starting secure server on "+listener.Addr().String())
147+
level.Info(logger).Log("msg", "Starting secure server on "+listener.Addr().String(), "http2", enableHTTP2)
148148
if err := srv.ServeTLS(listener, "", ""); err != http.ErrServerClosed {
149149
return err
150150
}
@@ -161,13 +161,23 @@ var (
161161
cfg = operator.DefaultConfig(defaultReloaderCPU, defaultReloaderMemory)
162162

163163
rawTLSCipherSuites string
164+
enableHTTP2 bool
164165
serverTLS bool
165166

166167
flagset = flag.CommandLine
167168
)
168169

169170
func init() {
170171
flagset.StringVar(&cfg.ListenAddress, "web.listen-address", ":8080", "Address on which to expose metrics and web interface.")
172+
// Mitigate CVE-2023-44487 by disabling HTTP2 by default until the Go
173+
// standard library and golang.org/x/net are fully fixed.
174+
// Right now, it is possible for authenticated and unauthenticated users to
175+
// hold open HTTP2 connections and consume huge amounts of memory.
176+
// See:
177+
// * https://github.com/kubernetes/kubernetes/pull/121120
178+
// * https://github.com/kubernetes/kubernetes/issues/121197
179+
// * https://github.com/golang/go/issues/63417#issuecomment-1758858612
180+
flagset.BoolVar(&enableHTTP2, "web.enable-http2", false, "Enable HTTP2 connections.")
171181
flagset.BoolVar(&serverTLS, "web.enable-tls", false, "Activate prometheus operator web server TLS. "+
172182
" This is useful for example when using the rule validation webhook.")
173183
flagset.StringVar(&cfg.ServerTLSConfig.CertFile, "web.cert-file", defaultOperatorTLSDir+"/tls.crt", "Cert file to be used for operator web server endpoints.")
@@ -494,6 +504,9 @@ func run() int {
494504
// and no datetime related flag to keep 'ts' field from base logger (with controlled format)
495505
ErrorLog: stdlog.New(log.NewStdlibAdapter(logger), "", stdlog.Lshortfile),
496506
}
507+
if !enableHTTP2 {
508+
srv.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler))
509+
}
497510
if srv.TLSConfig == nil {
498511
wg.Go(serve(srv, l, logger))
499512
} else {

0 commit comments

Comments
 (0)