88#include " source/extensions/filters/network/ssh/filter_state_objects.h"
99#include " source/extensions/filters/network/ssh/wire/common.h"
1010#include " source/extensions/filters/network/ssh/wire/messages.h"
11- #include < cstddef>
1211
1312#pragma clang unsafe_buffer_usage begin
1413#include " envoy/config/endpoint/v3/endpoint.pb.h"
1514#include " envoy/config/endpoint/v3/endpoint.pb.validate.h"
1615#include " source/common/network/connection_impl.h"
16+ #include " source/extensions/io_socket/user_space/io_handle_impl.h"
1717#include " source/common/network/connection_socket_impl.h"
1818#include " envoy/network/client_connection_factory.h"
1919#include " source/common/grpc/common.h"
@@ -87,6 +87,8 @@ class RemoteStreamHandler : public Logger::Loggable<Logger::Id::filter>,
8787 };
8888 *local_queue = &local_queue_;
8989
90+ remote_stream_handler_sync.syncPoint (" initialize" );
91+
9092 // The remote dispatcher could be running concurrently, but it won't pick up this callback
9193 // until after the next time it acquires post_lock_ (see dispatcher_impl.cc). Because this call
9294 // to post() adds the callback to the queue while holding post_lock_, the write to peer_state_
@@ -97,13 +99,16 @@ class RemoteStreamHandler : public Logger::Loggable<Logger::Id::filter>,
9799 remote_dispatcher_.post ([this ] {
98100 initialized_ = true ;
99101 // First check if the socket has been closed
102+ bool isDynamic = metadata_->server_port ().is_dynamic ();
100103 if (socket_closed_) {
101- ENVOY_LOG (debug, " channel {}: downstream closed before initialization" );
102- onError (absl::CancelledError (" downstream closed" ));
104+ ENVOY_LOG (debug, " channel {}: downstream closed before initialization" , peer_state_.id );
105+ // If the downstream closes before sending any data, and the upstream is expecting a SOCKS
106+ // handshake, we have to send it an EOF before closing the channel because openssh client
107+ // can become stuck
108+ onError (absl::CancelledError (" downstream closed" ), isDynamic);
103109 return ;
104110 }
105111 ENVOY_LOG (debug, " channel {}: remote stream handler initialized" , peer_state_.id );
106- bool isDynamic = metadata_->server_port ().is_dynamic ();
107112 if (isDynamic) {
108113 ENVOY_LOG (debug, " channel {}: starting socks5 handshake" , peer_state_.id );
109114 startSocks5Handshake ();
@@ -145,13 +150,15 @@ class RemoteStreamHandler : public Logger::Loggable<Logger::Id::filter>,
145150private:
146151 // Network::ConnectionCallbacks
147152 void onEvent (Network::ConnectionEvent event) override {
153+ ENVOY_LOG (debug, " downstream connection event: {}" , std::to_underlying (event));
148154 // These events are from the perspective of the downstream client connection, so LocalClose
149155 // means the downstream closed the connection, and RemoteClose means the upstream (us) closed
150156 // the connection.
151157 if (event == Network::ConnectionEvent::LocalClose ||
152158 event == Network::ConnectionEvent::RemoteClose) {
153159 // This is the last event received; the downstream connection will be destroyed and it is
154160 // safe to delete this object.
161+ remote_stream_handler_sync.syncPoint (" downstream_closed" );
155162 socket_closed_ = true ;
156163 if (!initialized_) {
157164 // Downstream closed before initialization
@@ -253,11 +260,12 @@ class RemoteStreamHandler : public Logger::Loggable<Logger::Id::filter>,
253260 onRemoteQueueReadyRead ();
254261 if (!received_channel_close_) {
255262 // If we didn't see a channel close, then shutdown() has not yet been called on the io handle.
256- ENVOY_LOG (debug, " channel {}: local peer exited without sending a ChannelClose message" );
263+ ENVOY_LOG (debug, " channel {}: local peer exited without sending a ChannelClose message" , peer_state_. id );
257264 }
258265 // Close it for reading and writing, since reads are impossible
259- ENVOY_BUG (io_handle_->isOpen (), " bug: io handle is closed" );
260- io_handle_->close ();
266+ if (io_handle_->isOpen ()) {
267+ io_handle_->close ();
268+ }
261269
262270 // If we did receive a channel close, allow the response to be received by the downstream.
263271 // Once that happens, we will receive the socket close event, where the deferred deletion is
@@ -1068,7 +1076,6 @@ class SshTunnelClientConnectionFactory : public ClientConnectionFactory,
10681076 auto & hostContext = streamAddress->hostContext ();
10691077 auto upstreamAddr = hostContext.clusterContext ().chooseUpstreamAddress ();
10701078
1071- ENVOY_LOG (debug, " channel {}: starting remote stream handler" );
10721079 using Extensions::NetworkFilters::GenericProxy::Codec::RemoteStreamHandler;
10731080 auto remoteStreamHandler = std::make_unique<RemoteStreamHandler>(std::move (local),
10741081 dispatcher,
0 commit comments