-
Notifications
You must be signed in to change notification settings - Fork 165
[connect-tcp] Improve recommendation for abrupt TLS termination #3141
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
39a29d3
ab1dc7e
bac9de6
de24813
15c5f37
3cc33c6
9fb6357
a3edc93
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -168,10 +168,13 @@ When closing connections, endpoints are subject to the following requirements: | |||
| * When a TCP connection reaches the TIME-WAIT or CLOSED state, the associated endpoint MUST close its send stream. | ||||
| - If the connection closed gracefully, the endpoint MUST close the send stream gracefully. | ||||
| - Otherwise, the endpoint SHOULD close the send stream abruptly, using a mechanism appropriate to the HTTP version: | ||||
| - HTTP/3: RESET_STREAM with H3_CONNECT_ERROR | ||||
| - HTTP/2: RST_STREAM with CONNECT_ERROR | ||||
| - HTTP/1.1 over TLS: a TLS Error Alert | ||||
| - HTTP/1.1 (insecure): TCP RST. | ||||
| - HTTP/3: reset the stream with H3_CONNECT_ERROR; | ||||
| see {{!RFC9000, Section 19.4}} and {{?RFC9114, Section 8.1}} | ||||
| - HTTP/2: reset the stream with CONNECT_ERROR; | ||||
| see {{!RFC9113}}, Sections 6.4 and 7 | ||||
| - HTTP/1.1 over TLS: TCP shutdown without a TLS closure alert; | ||||
| see {{!RFC8446, Section 6.1}}. | ||||
| - HTTP/1.1 without TLS: TCP RST | ||||
| * When the receive stream is closed abruptly or without a FINAL_DATA capsule received, the endpoint SHOULD send a TCP RST if the TCP subsystem permits it. | ||||
|
|
||||
| The mandatory behaviors above enable endpoints to detect any truncation of incoming TCP data. The recommended behaviors propagate any TCP errors through the proxy connection. | ||||
|
|
@@ -204,7 +207,7 @@ The mandatory behaviors above enable endpoints to detect any truncation of incom | |||
| +-+-----+ +-+----------+ +----------+-+ +-----+-+ | ||||
| +---"abc"--->+-------DATA{"abc"}------->+---"abc"--->| | ||||
| | | (... timeout @ A ...) | | | ||||
| | +--------TLS Alert-------->+----RST---->| | ||||
| | +--FIN (no close_notify)-->+----RST---->| | ||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Many implementation will treat this as a normal stream termination. That's because this is indistinguishable from a successful termination in the case that the TLS close_notify doesn't get sent (or doesn't make it through). I would not show any message being exchanged here at all.
Suggested change
Of course, this is based on you RECOMMENDING that no close_notify be sent. That's not something I would endorse. The right way to deal with this in HTTP/1.1 is to use chunked encoding or Content-Length properly. If the connection ends before the request is terminated, then it's an abortive close.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Do you mean implementations of TLS, or of "connect-tcp"? I assume that the major implementations of TLS correctly surface an error when close_notify is omitted at shutdown; otherwise some uses would be vulnerable to truncation attacks. Implementations of "connect-tcp" do not yet exist, and can be asked to conform. My main concern would be about TLS-terminating load balancers that always send close_notify.
I don't understand. When
Is there a reason why this recommendation is dangerous or problematic?
In HTTP/1.1, "connect-tcp" uses HTTP Upgrade, so Content-Length and chunked encoding are not available. Instead, it uses the Capsule Protocol (similar to chunked encoding).
"connect-tcp" employs a FINAL_DATA capsule to represent the TCP FIN (end of incoming data), without any reliance on the HTTP transport/stream. However, according to RFC 9293 that's not the same as "closed":
To get to the CLOSED state, you need a signal for "received ACK of FIN". In H2/H3, the draft uses graceful stream closure for that. In H1 over TLS, close_notify seems to be the equivalent signal.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I was talking about HTTP generally. In the timeout case, you don't need to mandate any particular behaviour. Because a timeout can be many things, including a clean termination (FINAL_DATA included) or not. You are attempting to proscribe actions that don't need that.
Because that's not how HTTP has worked so far and you are attempting to levy implementation requirements where they are most likely unwelcome. It might be appealing to have all implementations do the same thing here, but our experience is that they don't and they probably won't change just because it would be nicer if they would. (ignore the stuff about message termination; that's what I get for not pulling in enough context)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm referring to a TCP user timeout, which is an error in TCP terms. It cannot be a clean shutdown because the endpoint does not know if all data was successfully received in both directions. My point in showing this example was partly to show that even with this level of detail, some information is still lost: all errors are collapsed into RST.
|
||||
| | | | | | ||||
| ~~~ | ||||
| {: title="Timeout example (HTTP/1.1)"} | ||||
|
|
@@ -237,7 +240,7 @@ Servers that host a proxy under this specification MAY offer support for TLS ear | |||
|
|
||||
| This specification supports the "Expect: 100-continue" request header ({{?RFC9110, Section 10.1.1}}) in any HTTP version. The "100 (Continue)" status code confirms receipt of a request at the proxy without waiting for the proxy-destination TCP handshake to succeed or fail. This might be particularly helpful when the destination host is not responding, as TCP handshakes can hang for several minutes before failing. Clients MAY send "Expect: 100-continue", and proxies MUST respect it by returning "100 (Continue)" if the request is not immediately rejected. | ||||
|
|
||||
| Proxies implementing this specification SHOULD include a "Proxy-Status" response header {{!RFC9209}} in any success or failure response (i.e., status codes 101, 2XX, 4XX, or 5XX) to support advanced client behaviors and diagnostics. In HTTP/2 or HTTP/3, proxies MAY additionally send a "Proxy-Status" trailer in the event of an unclean shutdown. | ||||
| Proxies implementing this specification SHOULD include a "Proxy-Status" response header {{!RFC9209}} in any success or failure response (i.e., status codes 101, 2XX, 4XX, or 5XX) to support advanced client behaviors and diagnostics. In HTTP/2 or HTTP/3, proxies MAY additionally send a "Proxy-Status" trailer in the event of an abrupt stream closure. | ||||
|
|
||||
| # Applicability | ||||
|
|
||||
|
|
@@ -291,7 +294,9 @@ A malicious client can achieve cause highly asymmetric resource usage at the pro | |||
| While this specification is fully functional under HTTP/1.1, performance-sensitive deployments SHOULD use HTTP/2 or HTTP/3 instead. When using HTTP/1.1: | ||||
|
|
||||
| * Each CONNECT request requires a new TCP and TLS connection, imposing a higher cost in setup latency, congestion control convergence, CPU time, and data transfer. | ||||
| * It may be difficult to implement the recommended unclean shutdown signals ({{closing-connections}}), as many TLS libraries do not support injecting TLS Alerts. | ||||
| * The graceful and abrupt closure signals ({{closing-connections}}) are more likely to be missing or corrupted: | ||||
| - Some implementations may be unable to emit the recommended abrupt closure signals, due to limitations in their TCP and TLS subsystems. | ||||
| - Faulty implementations may fail to send a TLS closure alert during graceful shutdown, or fail to report an error when the expected closure alert is not received. These misbehaviors are not compliant with {{RFC8446}}, but they are common nonetheless among HTTP/1.1 implementations today. | ||||
| * The number of active connections through each client may be limited by the number of available TCP client ports, especially if: | ||||
| - The client only has one IP address that can be used to reach the proxy. | ||||
| - The client is shared between many parties, such as when acting as a gateway or concentrator. | ||||
|
|
||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Closure with a close_notify after receiving a FINAL_DATA capsule (representing FIN) would indicate graceful close. The purpose of this line is to provide a signal of ungraceful close (i.e. RST or timeout) that can be used after receiving the FIN (but before the connection is closed).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As noted above, either works if you don't have FINAL_DATA, so why attempt to fix implementations.