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