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>
