SSH ControlMaster: Retrying slave channels during master connection timeouts
0 reputation · 07 Jan 2020, 11:12 UTC
0 reputation · 07 Jan 2020, 11:12 UTC
OpenSSH utilizes ControlMaster and ControlPersist to allow multiple sessions to share a single TCP connection, bypassing repeated authentication handshakes for subsequent slave channels.
A technical uncertainty exists when a master connection experiences a network timeout while a slave channel is in the process of retrying a command. If the client transparently attempts to reconnect the master connection, the behavior regarding buffered data from the failed slave session is not explicitly guaranteed.
Depending on the ServerAliveInterval and ServerAliveCountMax configurations, it is unclear if the client ensures the atomicity of the write operation or if the retry mechanism could lead to duplicated data transmission upon master recovery.
ControlMaster reconnection event?30775 reputation · 07 Jan 2020, 16:53 UTC
OpenSSH does not transparently re-establish a master connection to recover active slave channels. If the master connection times out or is severed, all multiplexed slave channels are terminated immediately. There is no native mechanism within OpenSSH to migrate an existing slave session's state or buffered data to a new master connection.
Because ControlMaster relies on a single underlying TCP socket, the slave channels are logical abstractions (SSH channels) within that one encrypted tunnel. When the master connection fails—whether due to a network timeout or a ServerAliveCountMax expiration—the TCP socket is closed. Since the state of the slave channel (including any unacknowledged data in the local buffer) exists only within the context of that specific socket, the data is discarded when the connection terminates.
If a client script attempts to "retry" a command by launching a new SSH process while the master is reconnecting, it is initiating a new slave channel on a new master connection. It is not resuming the previous session. Consequently, any data that was buffered but not acknowledged by the server before the first master connection failed may be sent again by the application layer, potentially leading to duplicate writes.
To prevent connection drops and the resulting data uncertainty, focus on maintaining the stability of the master connection rather than attempting to recover slave channels:
ServerAliveInterval and ServerAliveCountMax to ensure the master connection remains active during idle periods.ControlPersist to keep the master connection open in the background, reducing the frequency of new handshake events.You can verify this behavior by observing the socket lifecycle:
ssh -M -S /tmp/ssh-socket user@hostssh -S /tmp/ssh-socket user@host "sleep 100"Diagnostic Detail Needed: Are you using a wrapper script or a specific automation tool (e.g., Ansible, Fabric) to handle the retries? The retry logic of the calling application determines whether duplicate writes occur, as OpenSSH itself does not perform transparent session migration.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.