Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 1 Jul 2001 21:45:47 -0500 (CDT)
From:      Mike Silbersack <silby@silby.com>
To:        Jonathan Lemon <jlemon@flugsvamp.com>
Cc:        Glenn Johnson <gjohnson@srrc.ars.usda.gov>, <net@freebsd.org>, <kris@freebsd.org>, Gilbert Gong <ggong@cal.alumni.berkeley.edu>
Subject:   Re: select fails to return incoming connect on FreeBSD-4.3
Message-ID:  <20010701214104.V1087-200000@achilles.silby.com>
In-Reply-To: <20010627220031.B10008@prism.flugsvamp.com>

next in thread | previous in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]

On Wed, 27 Jun 2001, Jonathan Lemon wrote:

> I don't object; while the security provided by the new scheme is nice,
> breaking TIME_WAIT assassination is a serious bug in some environments,
> and there should be a way to work around it now.
> --
> Jonathan

Ok, attached is a patch for 4.3-stable which makes the generation scheme
sysctl selectable.  You use the sysctl net.inet.tcp.tcp_seq_genscheme to
set which scheme you want.  0 is the old random positive increments
scheme, 1 is the more random OpenBSD scheme.  1 is the default setting, so
those encountering the TIME_WAIT problem will have to put something in a
boot script to set the variable to 0.

There's one slight difference in this implementation of the old scheme
versus the old implementation of it.  Before, we used TCP_ISSINCR/2 for
outgoing incrementations, and /4 for incoming.  We use /2 in both cases
now, for simplicity's sake.

Please review, especially if you're experiencing the TIME_WAIT problem.

Thanks,

Mike "Silby" Silbersack

[-- Attachment #2 --]
diff -u -r netinet.old/tcp_input.c netinet/tcp_input.c
--- netinet.old/tcp_input.c	Sun Jul  1 20:44:50 2001
+++ netinet/tcp_input.c	Sun Jul  1 21:17:58 2001
@@ -1080,7 +1080,7 @@
 		if (iss)
 			tp->iss = iss;
 		else {
-			tp->iss = tcp_rndiss_next();
+			tp->iss = tcp_new_isn();
  		}
 		tp->irs = th->th_seq;
 		tcp_sendseqinit(tp);
@@ -1612,7 +1612,7 @@
 			if (thflags & TH_SYN &&
 			    tp->t_state == TCPS_TIME_WAIT &&
 			    SEQ_GT(th->th_seq, tp->rcv_nxt)) {
-				iss = tcp_rndiss_next();
+				iss = tcp_new_isn();
 				tp = tcp_close(tp);
 				goto findpcb;
 			}
diff -u -r netinet.old/tcp_seq.h netinet/tcp_seq.h
--- netinet.old/tcp_seq.h	Sun Jul  1 20:44:50 2001
+++ netinet/tcp_seq.h	Sun Jul  1 21:08:02 2001
@@ -81,6 +81,24 @@
 #ifdef _KERNEL
 extern tcp_cc	tcp_ccgen;		/* global connection count */
 
+/*
+ * Increment for tcp_iss each second.
+ * This is designed to increment at the standard 250 KB/s,
+ * but with a random component averaging 128 KB.
+ * We also increment tcp_iss by a quarter of this amount
+ * each time we use the value for a new connection.
+ * If defined, the tcp_random18() macro should produce a
+ * number in the range [0-0x3ffff] that is hard to predict.
+ * 
+ * The variable tcp_iss and tcp_random18() are only used
+ * by sequence number generation scheme 0.
+ */
+#ifndef tcp_random18
+#define	tcp_random18()	(arc4random() & 0x3ffff)
+#endif
+#define	TCP_ISSINCR	(122*1024 + tcp_random18())
+
+extern tcp_seq	tcp_iss;
 #else
 #define	TCP_ISSINCR	(250*1024)	/* increment for tcp_iss each second */
 #endif /* _KERNEL */
diff -u -r netinet.old/tcp_subr.c netinet/tcp_subr.c
--- netinet.old/tcp_subr.c	Sun Jul  1 20:44:50 2001
+++ netinet/tcp_subr.c	Sun Jul  1 21:35:14 2001
@@ -139,6 +139,10 @@
 SYSCTL_INT(_net_inet_tcp, OID_AUTO, icmp_may_rst, CTLFLAG_RW, &icmp_may_rst, 0, 
     "Certain ICMP unreachable messages may abort connections in SYN_SENT");
 
+static int	tcp_seq_genscheme = 1;
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, tcp_seq_genscheme, CTLFLAG_RW,
+    &tcp_seq_genscheme, 0, "TCP ISN generation scheme");
+
 static void	tcp_cleartaocache __P((void));
 static void	tcp_notify __P((struct inpcb *, int));
 
@@ -182,6 +186,7 @@
 {
 	int hashsize;
 	
+	tcp_iss = arc4random();	/* wrong, but better than a constant */
 	tcp_ccgen = 1;
 	tcp_cleartaocache();
 
@@ -1086,6 +1091,26 @@
 			      0, cmd, notify);
 }
 #endif /* INET6 */
+
+tcp_seq
+tcp_new_isn()
+{
+	if ((tcp_seq_genscheme > 1) || (tcp_seq_genscheme < 0))
+		tcp_seq_genscheme = 1;
+
+	switch (tcp_seq_genscheme) {
+		case 0:	/*
+			 * Random positive increments
+			 */
+			tcp_iss += TCP_ISSINCR/2;
+			return tcp_iss;
+		case 1:	/*
+			 * OpemBSD randomized scheme
+			 */
+			return tcp_rndiss_next();
+	}
+
+}
 
 #define TCP_RNDISS_ROUNDS	16
 #define TCP_RNDISS_OUT	7200
diff -u -r netinet.old/tcp_timer.c netinet/tcp_timer.c
--- netinet.old/tcp_timer.c	Sun Jul  1 20:44:50 2001
+++ netinet/tcp_timer.c	Sun Jul  1 21:12:16 2001
@@ -132,6 +132,8 @@
 
 	tcp_maxidle = tcp_keepcnt * tcp_keepintvl;
 
+	tcp_iss += TCP_ISSINCR/PR_SLOWHZ;
+
 	splx(s);
 }
 
diff -u -r netinet.old/tcp_usrreq.c netinet/tcp_usrreq.c
--- netinet.old/tcp_usrreq.c	Sun Jul  1 20:44:50 2001
+++ netinet/tcp_usrreq.c	Sun Jul  1 21:18:20 2001
@@ -759,7 +759,7 @@
 	tcpstat.tcps_connattempt++;
 	tp->t_state = TCPS_SYN_SENT;
 	callout_reset(tp->tt_keep, tcp_keepinit, tcp_timer_keep, tp);
-	tp->iss = tcp_rndiss_next();
+	tp->iss = tcp_new_isn();
 	tcp_sendseqinit(tp);
 
 	/*
@@ -851,7 +851,7 @@
 	tcpstat.tcps_connattempt++;
 	tp->t_state = TCPS_SYN_SENT;
 	callout_reset(tp->tt_keep, tcp_keepinit, tcp_timer_keep, tp);
-	tp->iss = tcp_rndiss_next();
+	tp->iss = tcp_new_isn();
 	tcp_sendseqinit(tp);
 
 	/*
diff -u -r netinet.old/tcp_var.h netinet/tcp_var.h
--- netinet.old/tcp_var.h	Sun Jul  1 20:44:50 2001
+++ netinet/tcp_var.h	Sun Jul  1 21:13:25 2001
@@ -413,6 +413,7 @@
 tcp_seq	tcp_rndiss_next __P((void));
 u_int16_t
 	tcp_rndiss_encrypt __P((u_int16_t));
+tcp_seq tcp_new_isn __P((void));
 
 #endif /* _KERNEL */
 

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010701214104.V1087-200000>