[ 
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)

Reply via email to