Idle SSH session disconnects (update)
Martin Johansson
martin at fatbob.nu
Mon Sep 9 23:58:58 EST 2002
If you do not have control over the sshd configuration so that you cannot
control ClientAlive-stuff, you can use the attached patch (against openssh
3.4p1). It adds 2 parameters to ssh_config:
BogusTrafficIntervalMax 12
BogusTrafficIntervalMin 1
This configures the ssh client to send SSH_MSG_IGNORE randomly after
between 1-12 seconds of idle time, thereby keeping the connection from
timing out in the FW.
Pretty useful for me who also sits behind a stateful FW.
/Martin
--- openssh-3.4p1/readconf.c Fri Jun 21 02:41:52 2002
+++ openssh-3.4p1.servalive/readconf.c Mon Sep 9 13:37:15 2002
@@ -114,6 +114,7 @@
oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
oClearAllForwardings, oNoHostAuthenticationForLocalhost,
+ oBogusTrafficIntervalMax, oBogusTrafficIntervalMin,
oDeprecated
} OpCodes;
@@ -177,6 +178,8 @@
{ "compression", oCompression },
{ "compressionlevel", oCompressionLevel },
{ "keepalive", oKeepAlives },
+ { "BogusTrafficIntervalMax", oBogusTrafficIntervalMax },
+ { "BogusTrafficIntervalMin", oBogusTrafficIntervalMin },
{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
{ "loglevel", oLogLevel },
{ "dynamicforward", oDynamicForward },
@@ -411,6 +414,42 @@
intptr = &options->no_host_authentication_for_localhost;
goto parse_flag;
+ case oBogusTrafficIntervalMax:
+ intptr = &options->bogus_traffic_interval_max;
+ arg = strdelim(&s);
+ if (!arg || *arg == '\0')
+ fatal("%.200s line %d: Missing argument.", filename, linenum);
+ if (arg[0] < '0' || arg[0] > '9')
+ fatal("%.200s line %d: Bad number.", filename, linenum);
+
+ /* Octal, decimal, or hex format? */
+ value = strtol(arg, &endofnumber, 0);
+ if (arg == endofnumber)
+ fatal("%.200s line %d: Bad number.", filename, linenum);
+ if (*activep && *intptr == -1)
+ *intptr = value;
+ if (options->bogus_traffic_interval_min >= value)
+ fatal("%.200s line %d: Bad value.", filename, linenum);
+ break;
+
+ case oBogusTrafficIntervalMin:
+ intptr = &options->bogus_traffic_interval_min;
+ arg = strdelim(&s);
+ if (!arg || *arg == '\0')
+ fatal("%.200s line %d: Missing argument.", filename, linenum);
+ if (arg[0] < '0' || arg[0] > '9')
+ fatal("%.200s line %d: Bad number.", filename, linenum);
+
+ /* Octal, decimal, or hex format? */
+ value = strtol(arg, &endofnumber, 0);
+ if (arg == endofnumber)
+ fatal("%.200s line %d: Bad number.", filename, linenum);
+ if (*activep && *intptr == -1)
+ *intptr = value;
+ if (options->bogus_traffic_interval_max <= value)
+ fatal("%.200s line %d: Bad value.", filename, linenum);
+ break;
+
case oNumberOfPasswordPrompts:
intptr = &options->number_of_password_prompts;
goto parse_int;
@@ -766,6 +805,8 @@
options->strict_host_key_checking = -1;
options->compression = -1;
options->keepalives = -1;
+ options->bogus_traffic_interval_max = -1;
+ options->bogus_traffic_interval_min = -1;
options->compression_level = -1;
options->port = -1;
options->connection_attempts = -1;
@@ -853,6 +894,10 @@
options->compression = 0;
if (options->keepalives == -1)
options->keepalives = 1;
+ if (options->bogus_traffic_interval_max == -1)
+ options->bogus_traffic_interval_max = 0;
+ if (options->bogus_traffic_interval_min == -1)
+ options->bogus_traffic_interval_min = 0;
if (options->compression_level == -1)
options->compression_level = 6;
if (options->port == -1)
--- openssh-3.4p1/clientloop.c Wed Jun 26 01:17:37 2002
+++ openssh-3.4p1.servalive/clientloop.c Mon Sep 9 13:35:58 2002
@@ -321,6 +321,9 @@
client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
int *maxfdp, int *nallocp, int rekeying)
{
+ struct timeval tv, *tvp;
+ int ret;
+
/* Add any selections by the channel mechanism. */
channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, rekeying);
@@ -362,13 +365,29 @@
/*
* Wait for something to happen. This will suspend the process until
* some selected descriptor can be read, written, or has some other
- * event pending. Note: if you want to implement SSH_MSG_IGNORE
- * messages to fool traffic analysis, this might be the place to do
- * it: just have a random timeout for the select, and send a random
- * SSH_MSG_IGNORE packet when the timeout expires.
+ * event pending.
+ * Set a random timeout for the select, and send a random SSH_MSG_IGNORE
+ * packet when the timeout expires to fool traffic analysis.
*/
-
- if (select((*maxfdp)+1, *readsetp, *writesetp, NULL, NULL) < 0) {
+ if (options.bogus_traffic_interval_max) {
+ u_int32_t rand = arc4random();
+ u_int64_t timeusec;
+ static u_int64_t timebase = 0;
+
+ if (!timebase)
+ timebase = (options.bogus_traffic_interval_max -
+ options.bogus_traffic_interval_min) * 1000000;
+ timeusec = timebase * rand / 0xffffffffUL;
+ timeusec += options.bogus_traffic_interval_min * 1000000;
+ tv.tv_sec = timeusec / 1000000;
+ tv.tv_usec = timeusec % 1000000;
+ tvp = &tv;
+ debug2("Will send SSH_MSG_IGNORE in %lu.%lu s", tv.tv_sec, tv.tv_usec);
+ }
+ else tvp = NULL;
+
+ ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
+ if (ret < 0) {
char buf[100];
/*
@@ -386,6 +405,12 @@
buffer_append(&stderr_buffer, buf, strlen(buf));
quit_pending = 1;
}
+ else if (ret == 0) { /* timeout */
+ u_int32_t rand = arc4random();
+ packet_send_ignore((rand & 0x3f) + 1);
+ packet_send();
+ packet_write_wait();
+ }
}
static void
--- openssh-3.4p1/readconf.h Sun Jun 9 22:04:03 2002
+++ openssh-3.4p1.servalive/readconf.h Mon Sep 9 13:35:58 2002
@@ -61,6 +61,16 @@
int compression_level; /* Compression level 1 (fast) to 9
* (best). */
int keepalives; /* Set SO_KEEPALIVE. */
+ int bogus_traffic_interval_max; /*
+ * max time value of SSH_MSG_IGNORE
+ * interval
+ */
+ int bogus_traffic_interval_min; /*
+ * min time value of SSH_MSG_IGNORE
+ * interval
+ */
+ int pam_authentication_via_kbd_int;
+
LogLevel log_level; /* Level for logging. */
int port; /* Port to connect. */
More information about the openssh-unix-dev
mailing list