|
| 1 | +From a0fd4b065528566eec54fe207aa5e3131babc378 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Monis Khan < [email protected]> |
| 3 | +Date: Sat, 7 Oct 2023 21:50:37 -0400 |
| 4 | +Subject: [PATCH] Prevent rapid reset http2 DOS on API server |
| 5 | + |
| 6 | +This change fully addresses CVE-2023-44487 and CVE-2023-39325 for |
| 7 | +the API server when the client is unauthenticated. |
| 8 | + |
| 9 | +The changes to util/runtime are required because otherwise a large |
| 10 | +number of requests can get blocked on the time.Sleep calls. |
| 11 | + |
| 12 | +For unauthenticated clients (either via 401 or the anonymous user), |
| 13 | +we simply no longer allow such clients to hold open http2 |
| 14 | +connections. They can use http2, but with the performance of http1 |
| 15 | +(with keep-alive disabled). |
| 16 | + |
| 17 | +Since this change has the potential to cause issues, the |
| 18 | +UnauthenticatedHTTP2DOSMitigation feature gate can be disabled to |
| 19 | +remove this protection (it is enabled by default). For example, |
| 20 | +when the API server is fronted by an L7 load balancer that is set up |
| 21 | +to mitigate http2 attacks, unauthenticated clients could force |
| 22 | +disable connection reuse between the load balancer and the API |
| 23 | +server (many incoming connections could share the same backend |
| 24 | +connection). An API server that is on a private network may opt to |
| 25 | +disable this protection to prevent performance regressions for |
| 26 | +unauthenticated clients. |
| 27 | + |
| 28 | +For all other clients, we rely on the golang.org/x/net fix in |
| 29 | +https://github.com/golang/net/commit/b225e7ca6dde1ef5a5ae5ce922861bda011cfabd |
| 30 | +That change is not sufficient to adequately protect against a |
| 31 | +motivated client - future changes to Kube and/or golang.org/x/net |
| 32 | +will be explored to address this gap. |
| 33 | + |
| 34 | +The Kube API server now uses a max stream of 100 instead of 250 |
| 35 | +(this matches the Go http2 client default). This lowers the abuse |
| 36 | +limit from 1000 to 400. |
| 37 | + |
| 38 | +Signed-off-by: Monis Khan < [email protected]> |
| 39 | + |
| 40 | +Modified by: corvus-callidus < [email protected]> |
| 41 | +- Adjust paths to apply to vendored code |
| 42 | +- Remove references to runtime_test.go which isn't included in the AzL3 package source |
| 43 | + |
| 44 | +Kubernetes-commit: 800a8eaba7f25bd223fefe6e7613e39a5d7f1eeb |
| 45 | +--- |
| 46 | + vendor/k8s.io/apimachinery/pkg/util/runtime/runtime.go | 15 +++++++++------ |
| 47 | + 1 files changed, 9 insertions(+), 6 deletions(-) |
| 48 | + |
| 49 | +diff --git a/vendor/k8s.io/apimachinery/pkg/util/runtime/runtime.go b/vendor/k8s.io/apimachinery/pkg/util/runtime/runtime.go |
| 50 | +index d738725ca..3674914f7 100644 |
| 51 | +--- a/vendor/k8s.io/apimachinery/pkg/util/runtime/runtime.go |
| 52 | ++++ b/vendor/k8s.io/apimachinery/pkg/util/runtime/runtime.go |
| 53 | +@@ -126,14 +126,17 @@ type rudimentaryErrorBackoff struct { |
| 54 | + // OnError will block if it is called more often than the embedded period time. |
| 55 | + // This will prevent overly tight hot error loops. |
| 56 | + func (r *rudimentaryErrorBackoff) OnError(error) { |
| 57 | ++ now := time.Now() // start the timer before acquiring the lock |
| 58 | + r.lastErrorTimeLock.Lock() |
| 59 | +- defer r.lastErrorTimeLock.Unlock() |
| 60 | +- d := time.Since(r.lastErrorTime) |
| 61 | +- if d < r.minPeriod { |
| 62 | +- // If the time moves backwards for any reason, do nothing |
| 63 | +- time.Sleep(r.minPeriod - d) |
| 64 | +- } |
| 65 | ++ d := now.Sub(r.lastErrorTime) |
| 66 | + r.lastErrorTime = time.Now() |
| 67 | ++ r.lastErrorTimeLock.Unlock() |
| 68 | ++ |
| 69 | ++ // Do not sleep with the lock held because that causes all callers of HandleError to block. |
| 70 | ++ // We only want the current goroutine to block. |
| 71 | ++ // A negative or zero duration causes time.Sleep to return immediately. |
| 72 | ++ // If the time moves backwards for any reason, do nothing. |
| 73 | ++ time.Sleep(r.minPeriod - d) |
| 74 | + } |
| 75 | + |
| 76 | + // GetCaller returns the caller of the function that calls it. |
0 commit comments