uncleanShutdown
should be handled automatically (where possible)
#238
Labels
kind/enhancement
Improvements to existing feature.
Milestone
TLS (SSL) encrypts, validates, and authenticates all the data that goes through the connection. That is a fantastic property to have and solves most issues. TLS however still runs over TCP and the control packets of TCP are not encrypted. This means that the one thing an attacker can still do on a TLS connection is to close it. The attacker could send RST or FIN packets the other peer and the receiving peer has no means to verify if this RST/FIN packet is actually coming from the other peer (as opposed to an attacker).
To fix this problem, TLS introduces a close_notify message that is send over connection as encrypted data. So if the other peer receives a close_notify it knows that it was truly sent by the other peer (and not an attacker). A well behaving peer would then reply to the
close_notify
with its ownclose_notify
and after that both peers can close the TCP connection because they know that the respective other peer knows they're okay closing it.Okay, but what's the issue with having a connection just close. Wouldn't I notice that part of the data is missing? The answer is it depends. Many protocols actually send to the other peer how much data they will send before sending the data. And they also have a well defined "end message". If you're using such a protocol, then an "unclean shutdown" (which is you have received a RST/FIN without a close_notify) is totally harmless. The higher level protocol allows you to distinguish between a truncated message (when there's still outstanding data) and a close after a completed message.
The reason SwiftNIO sends you a
NIOSSLError.uncleanShutdown
if it sees a connection closing without a priorclose_notify
is because it doesn't know what protocol you're implementing. Maybe the protocol you speak doesn't transmit length information so a truncated message cannot be told apart from a complete message.Let's go into some example protocols and their behaviour regarding framing:
content-length
header is unaffected by truncation attacks because we know the content length. So if the connection closes before we have received that many bytes, we know it was a truncated message (either by an attacker injecting a FIN/RST, or by a software/network problem somewhere along the way)0\r\n\r\n
). Unfortunately HTTP/1 can be used without eithertransfer-encoding: chunked
orcontent-length
. It then runs in the "EOF framing" mode which means that the message ends when we receive a connection close 😢 . Very bad, if HTTP/1 is used in "EOF framing" mode, then an unclean shutdown is actually a real error because we cannot tell a truncated message apart from a complete message.Why should AHC do better here? Well, AHC knows if its speaking HTTP/1 or HTTP/2 and whether the server sent a
content-length
ortransfer-encoding: chunked
or not. Therefore, AHC should suppress the uncleanShutdown error in all cases apart from when HTTP/1 is run in "EOF framing mode".The good news is that this will almost never happen. Nobody in their right mind uses EOF framing mode.
The text was updated successfully, but these errors were encountered: