[
https://issues.apache.org/jira/browse/KAFKA-21341?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Manikumar resolved KAFKA-21341.
-------------------------------
Resolution: Fixed
> SslTransportLayer does not report a disconnect when the peer sends
> close_notify without a TCP FIN
> -------------------------------------------------------------------------------------------------
>
> Key: KAFKA-21341
> URL: https://issues.apache.org/jira/browse/KAFKA-21341
> Project: Kafka
> Issue Type: Bug
> Components: clients, network
> Affects Versions: 3.6.0, 3.6.1, 3.6.2, 3.6.3, 3.7.0, 3.7.1, 3.7.2, 3.7.3,
> 3.8.0, 3.8.1, 3.8.2, 3.9.0, 3.9.1, 3.9.2, 4.0.0, 4.0.1, 4.1.0, 4.2.0, 4.3.0,
> 4.0.2, 4.1.1, 4.1.2, 4.2.1, 3.9.3, 4.1.3, 4.0.3, 4.3.1, 4.4.0, 4.2.2, 4.3.2,
> 4.5.0, 4.4.1, 4.3.3, 4.2.3
> Reporter: Truc Nguyen
> Assignee: Truc Nguyen
> Priority: Major
> Fix For: 4.5.0
>
>
> When a TLS close_notify arrives in the same socket read as application data,
> SslTransportLayer.read() returns the data and leaves the close to be handled
> by a later read. However, updateBytesBuffered() clears hasBytesBuffered once
> the buffers are empty, so the Selector only reads the channel again if the
> socket becomes readable, which requires a TCP FIN.
> RFC 8446 section 6.1 allows a peer to send close_notify and keep the TCP
> connection open: close_notify closes only the sender's write side, and the
> standard leaves the transport lifecycle to the application. A TLS-terminating
> proxy that half-closes its TLS side (for example, Envoy's tcp_proxy) does
> exactly this. The client then never notices the disconnect, and an in-flight
> request waits for request.timeout.ms before it fails.
> *Reproduction*
> A TLS peer completes the handshake, then writes part (or all) of a response
> followed by close_notify in a single write, and keeps the TCP connection
> open. The client Selector never reports the connection as disconnected. If
> the full response was sent, the client receives it but still does not see the
> disconnect.
> *Expected behaviour*
> Kafka already treats close_notify as end-of-stream when it arrives on its
> own: the CLOSED unwrap makes read() throw EOFException and the channel is
> closed. It should do the same when close_notify arrives together with data.
> This matches RFC 8446 section 6.1, which requires a TLS implementation to
> receive close_notify before indicating end-of-data to the application, and
> does not require the receiver to keep its own write side open. Kafka has no
> half-close semantics: once the peer has sent close_notify it can send no more
> responses, so reporting the disconnect at once is the only useful behaviour.
> On close, SslTransportLayer still sends its own close_notify.
> *Proposed fix*
> * After a CLOSED unwrap, keep the channel in the Selector's buffered-read set
> (hasBytesBuffered = true) so the next poll() reads it again without waiting
> for OP_READ.
> * At the start of read(), if the engine's inbound side is done and no
> decrypted data is left, throw EOFException so the channel is closed as a
> disconnect.
> * In read(ByteBuffer[], int, int), return the bytes already read if a later
> read throws EOFException, instead of losing them.
> A channel that is muted (for example while the broker handles a request that
> arrived with the close_notify) stays open until it is unmuted, so the
> response to that request is still sent before the disconnect is reported.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)