Subject: How should my libssh2-based client handle gratuitous keepalives from the ssh server?

How should my libssh2-based client handle gratuitous keepalives from the ssh server?

From: Jeremy Friesner <jeremyf_at_meyersound.com>
Date: Wed, 17 Jan 2018 20:22:37 +0000

Hi all,

I’ve got a GUI client program that uses libssh2 to connect via SSH to a vanilla sshd server (i.e. the one that ships with Debian Linux). Once it connects, it opens an ssh channel to send a few shell commands that collect some data from the server, and when it gets the responses back it closes the channel while keeping the SSH session open, and waits for the user to do something. This is all implemented using the non-blocking model, with an event loop based around select().

This is all working fine (and has been working fine for a number of years), but I’ve noticed that with some newer servers we connect to, after about 15 seconds of connected idle time, the sshd server starts spontaneously sending unrequested keepalive messages to the client. These messages are 68 bytes long each, and the server sends four of them, and then closes the connection (presumably because my client didnt’ respond to the keepalives).

If I look in the server’s /etc/ssh/sshd_config file, sure enough there is this:

ClientAliveInterval 15
ClientAliveCountMax 4

… so one work-around for the problem would probably be to change the server’s settings to disable this behavior, but I’d prefer to have a client that can handle keepalives properly, since I might not always be have permission to change settings on the server.

So my question is, how can my non-blocking client correctly handle (and respond to) these keepalive packets? Currently it just goes into a spinloop (because select() sees the bytes available-for-read on the socket, but I don’t know what libssh2 function to call in order to absorb them). I can recv() the bytes directly and throw them away myself, but that risks messing up libssh2’s internal state machines if I accidentally read any non-keepalive data, and in any case it doesn’t send a response back to the server, so the server will still hang up on me after a minute. I tried calling libssh2_poll() to see if that would allow the libssh2 code to read and handle the keepalives, but that didn’t seem to have any effect.

Is there a recommended way to handle this issue?

Thanks,
Jeremy

_______________________________________________
libssh2-devel https://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel
Received on 2018-01-17