Skip to content

Commit a81afe0

Browse files
authored
Implementation of GEP-3567 - TLS Updates for Connection Coalescing (#3630)
* Implementation of GEP-3567 - TLS Updates for Connection Coalescing * Responses to PR feedback
1 parent 79af272 commit a81afe0

File tree

6 files changed

+188
-24
lines changed

6 files changed

+188
-24
lines changed

apis/v1/gateway_types.go

Lines changed: 81 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -336,10 +336,31 @@ type Listener struct {
336336
//
337337
// * TLS: The Listener Hostname MUST match the SNI.
338338
// * HTTP: The Listener Hostname MUST match the Host header of the request.
339-
// * HTTPS: The Listener Hostname SHOULD match at both the TLS and HTTP
340-
// protocol layers as described above. If an implementation does not
341-
// ensure that both the SNI and Host header match the Listener hostname,
342-
// it MUST clearly document that.
339+
// * HTTPS: The Listener Hostname SHOULD match both the SNI and Host header.
340+
// Note that this does not require the SNI and Host header to be the same.
341+
// The semantics of this are described in more detail below.
342+
//
343+
// To ensure security, Section 11.1 of RFC-6066 emphasizes that server
344+
// implementations that rely on SNI hostname matching MUST also verify
345+
// hostnames within the application protocol.
346+
//
347+
// Section 9.1.2 of RFC-7540 provides a mechanism for servers to reject the
348+
// reuse of a connection by responding with the HTTP 421 Misdirected Request
349+
// status code. This indicates that the origin server has rejected the
350+
// request because it appears to have been misdirected.
351+
//
352+
// To detect misdirected requests, Gateways SHOULD match the authority of
353+
// the requests with all the SNI hostname(s) configured across all the
354+
// Gateway Listeners on the same port and protocol:
355+
//
356+
// * If another Listener has an exact match or more specific wildcard entry,
357+
// the Gateway SHOULD return a 421.
358+
// * If the current Listener (selected by SNI matching during ClientHello)
359+
// does not match the Host:
360+
// * If another Listener does match the Host the Gateway SHOULD return a
361+
// 421.
362+
// * If no other Listener matches the Host, the Gateway MUST return a
363+
// 404.
343364
//
344365
// For HTTPRoute and TLSRoute resources, there is an interaction with the
345366
// `spec.hostnames` array. When both listener and route specify hostnames,
@@ -1268,6 +1289,62 @@ const (
12681289
ListenerReasonPending ListenerConditionReason = "Pending"
12691290
)
12701291

1292+
const (
1293+
// This condition indicates that TLS configuration within this Listener
1294+
// conflicts with TLS configuration in another Listener on the same port.
1295+
// This could happen for two reasons:
1296+
//
1297+
// 1) Overlapping Hostnames: Listener A matches *.example.com while Listener
1298+
// B matches foo.example.com.
1299+
// B) Overlapping Certificates: Listener A contains a certificate with a
1300+
// SAN for *.example.com, while Listener B contains a certificate with a
1301+
// SAN for foo.example.com.
1302+
//
1303+
// This overlapping TLS configuration can be particularly problematic when
1304+
// combined with HTTP connection coalescing. When clients reuse connections
1305+
// using this technique, it can have confusing interactions with Gateway
1306+
// API, such as TLS configuration for one Listener getting used for a
1307+
// request reusing an existing connection that would not be used if the same
1308+
// request was initiating a new connection.
1309+
//
1310+
// Controllers MUST detect the presence of overlapping hostnames and MAY
1311+
// detect the presence of overlapping certificates.
1312+
//
1313+
// This condition MUST be set on all Listeners with overlapping TLS config.
1314+
// For example, consider the following listener - hostname mapping:
1315+
//
1316+
// A: foo.example.com
1317+
// B: foo.example.org
1318+
// C: *.example.com
1319+
//
1320+
// In the above example, Listeners A and C would have overlapping hostnames
1321+
// and therefore this condition should be set for Listeners A and C, but not
1322+
// B.
1323+
//
1324+
// Possible reasons for this condition to be True are:
1325+
//
1326+
// * "OverlappingHostnames"
1327+
// * "OverlappingCertificates"
1328+
//
1329+
// If a controller supports checking for both possible reasons and finds
1330+
// that both are true, it SHOULD set the "OverlappingCertificates" Reason.
1331+
//
1332+
// This is a negative polarity condition and MUST NOT be set when it is
1333+
// False.
1334+
//
1335+
// Controllers may raise this condition with other reasons, but should
1336+
// prefer to use the reasons listed above to improve interoperability.
1337+
ListenerConditionOverlappingTLSConfig ListenerConditionType = "OverlappingTLSConfig"
1338+
1339+
// This reason is used with the "OverlappingTLSConfig" condition when the
1340+
// condition is true.
1341+
ListenerReasonOverlappingHostnames ListenerConditionReason = "OverlappingHostnames"
1342+
1343+
// This reason is used with the "OverlappingTLSConfig" condition when the
1344+
// condition is true.
1345+
ListenerReasonOverlappingCertificates ListenerConditionReason = "OverlappingCertificates"
1346+
)
1347+
12711348
const (
12721349
// "Ready" is a condition type reserved for future use. It should not be used by implementations.
12731350
// Note: This condition is not really "deprecated", but rather "reserved"; however, deprecated triggers Go linters

config/crd/experimental/gateway.networking.k8s.io_gateways.yaml

Lines changed: 50 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/standard/gateway.networking.k8s.io_gateways.yaml

Lines changed: 50 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

geps/gep-3567/index.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# GEP-3567: Gateway TLS Updates for HTTP/2 Connection Coalescing
22

33
* Issue: [#3567](https://github.com/kubernetes-sigs/gateway-api/issues/3567)
4-
* Status: Implementable
4+
* Status: Experimental
55

66
## TLDR
77

@@ -40,7 +40,9 @@ the client sends.
4040

4141
Gateway API deals with this situation imprecisely, stating:
4242

43-
The Listener Hostname SHOULD match at both the TLS and HTTP protocol layers as described above. If an implementation does not ensure that both the SNI and Host header match the Listener hostname, it MUST clearly document that.
43+
The Listener Hostname SHOULD match at both the TLS and HTTP protocol layers
44+
as described above. If an implementation does not ensure that both the SNI
45+
and Host header match the Listener hostname, it MUST clearly document that.
4446

4547
In practice we can end up with an implementation that misroutes requests when a
4648
Gateway is configured using certificates that use multiple or wildcard SANs.
@@ -119,7 +121,7 @@ A new condition will be added to Gateways: `OverlappingTLSConfig`.
119121
Implementations MUST add this condition to status when a Gateway is configured
120122
with TLS configuration across multiple Listeners. Implementations MAY add this
121123
condition to status when a Gateway is configured with overlapping TLS
122-
certifications. Note that since this is a negative polarity condition, it would
124+
certificates. Note that since this is a negative polarity condition, it would
123125
only be populated when it is true.
124126

125127
### B) Modify API Spec to recommend sending 421s

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ nav:
141141
- geps/gep-2649/index.md
142142
- geps/gep-3155/index.md
143143
- geps/gep-3171/index.md
144+
- geps/gep-3567/index.md
144145
- Standard:
145146
- geps/gep-709/index.md
146147
- geps/gep-718/index.md

pkg/generated/openapi/zz_generated.openapi.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)