sshd: ClientAlive{CountMax,Interval} fires twice each interval if connection is interrupted
dev at sapalski.de
dev at sapalski.de
Wed Sep 26 21:09:57 AEST 2018
I've discovered a bug in
serverloop.c(function=wait_until_can_do_something) for which I believe
that it wasn't reported so far.
With latest openssh (7.8p1 as well as current master) sshd disconnects a
non-responding client after approximately: (ClientAliveCountMax / 2) *
ClientAliveInterval
I did a bisect which showed that the fix introduced for bz#2756 causes
this behavior: https://bugzilla.mindrot.org/show_bug.cgi?id=2756
How to reproduce:
1. server #> /sbin/sshd -p 2020 -ddd -f ${sshd_config} 2>&1 | ts
2. client $> ssh $IP -p2020
3. close e.g. notebook of the client connection and wait for the
timeout to happen
${sshd_config}
----
TCPKeepAlive no
ClientAliveInterval 15
ClientAliveCountMax 8
----
The debug log of sshd shows:
----
...
[2018-04-26 11:59:35] debug3: /tmp/sshd_config:94 setting TCPKeepAlive
no
[2018-04-26 11:59:35] debug3: /tmp/sshd_config:98 setting
ClientAliveInterval 15
[2018-04-26 11:59:35] debug3: /tmp/sshd_config:99 setting
ClientAliveCountMax 8
...
[2018-04-26 12:00:16] debug2: channel 0: request keepalive at openssh.com
confirm 1
[2018-04-26 12:00:16] debug2: channel 0: request keepalive at openssh.com
confirm 1
[2018-04-26 12:00:31] debug2: channel 0: request keepalive at openssh.com
confirm 1
[2018-04-26 12:00:31] debug2: channel 0: request keepalive at openssh.com
confirm 1
[2018-04-26 12:00:46] debug2: channel 0: request keepalive at openssh.com
confirm 1
[2018-04-26 12:00:46] debug2: channel 0: request keepalive at openssh.com
confirm 1
[2018-04-26 12:01:01] debug2: channel 0: request keepalive at openssh.com
confirm 1
[2018-04-26 12:01:01] debug2: channel 0: request keepalive at openssh.com
confirm 1
[2018-04-26 12:01:16] Timeout, client not responding from user $USER
x.x.x.x port xxxxx
----
As we can see, keepalive packets are sent twice on every interval. I
think the problem is that if a timeout of the select call in
function=wait_until_can_do_something happens the
variable=last_client_time isn't set to current time and during the next
iteration the select call returns immediately with data contained in
'writesetp'.
A possible fix for which I believe doesn't break the fix of bz#2756 and
solves this problem could be:
----
diff --git a/serverloop.c b/serverloop.c
index d71724e..7110bf6 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -290,6 +290,7 @@ wait_until_can_do_something(struct ssh *ssh,
if (ret == 0) { /* timeout */
client_alive_check(ssh);
+ last_client_time = now;
} else if (FD_ISSET(connection_in, *readsetp)) {
last_client_time = now;
} else if (last_client_time != 0 && last_client_time +
----
This solves the problem for me. Can someone confirm that this is a bug
and apply either my proposed fix or any other which solves this problem?
If this gets confirmed, shall I open a bugzilla ticket or isn't it
necessary?
Thanks,
Samuel
More information about the openssh-unix-dev
mailing list