Temporary feature: Runtime tuneable tcp initial sequence number
generation scheme. Users may now select between the currently used OpenBSD algorithm and the older random positive increment method. While the OpenBSD algorithm is more secure, it also breaks TIME_WAIT handling; this is causing trouble for an increasing number of folks. To switch between generation schemes, one sets the sysctl net.inet.tcp.tcp_seq_genscheme. 0 = random positive increments, 1 = the OpenBSD algorithm. 1 is still the default. Once a secure _and_ compatible algorithm is implemented, this sysctl will be removed. Reviewed by: jlemon Tested by: numerous subscribers of -net
This commit is contained in:
parent
4718c85a24
commit
2d610a5028
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=79413
@ -1135,7 +1135,7 @@ tcp_input(m, off0, proto)
|
||||
if (iss)
|
||||
tp->iss = iss;
|
||||
else {
|
||||
tp->iss = tcp_rndiss_next();
|
||||
tp->iss = tcp_new_isn();
|
||||
}
|
||||
tp->irs = th->th_seq;
|
||||
tcp_sendseqinit(tp);
|
||||
@ -1667,7 +1667,7 @@ tcp_input(m, off0, proto)
|
||||
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;
|
||||
}
|
||||
|
@ -1135,7 +1135,7 @@ tcp_input(m, off0, proto)
|
||||
if (iss)
|
||||
tp->iss = iss;
|
||||
else {
|
||||
tp->iss = tcp_rndiss_next();
|
||||
tp->iss = tcp_new_isn();
|
||||
}
|
||||
tp->irs = th->th_seq;
|
||||
tcp_sendseqinit(tp);
|
||||
@ -1667,7 +1667,7 @@ tcp_input(m, off0, proto)
|
||||
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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -139,6 +139,10 @@ static int icmp_may_rst = 1;
|
||||
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 @@ tcp_init()
|
||||
{
|
||||
int hashsize = TCBHASHSIZE;
|
||||
|
||||
tcp_iss = arc4random(); /* wrong, but better than a constant */
|
||||
tcp_ccgen = 1;
|
||||
tcp_cleartaocache();
|
||||
|
||||
@ -1107,6 +1112,26 @@ tcp6_ctlinput(cmd, sa, d)
|
||||
}
|
||||
#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
|
||||
#define TCP_RNDISS_MAX 30000
|
||||
|
@ -133,6 +133,8 @@ tcp_slowtimo()
|
||||
|
||||
tcp_maxidle = tcp_keepcnt * tcp_keepintvl;
|
||||
|
||||
tcp_iss += TCP_ISSINCR/PR_SLOWHZ;
|
||||
|
||||
splx(s);
|
||||
}
|
||||
|
||||
|
@ -139,6 +139,10 @@ static int icmp_may_rst = 1;
|
||||
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 @@ tcp_init()
|
||||
{
|
||||
int hashsize = TCBHASHSIZE;
|
||||
|
||||
tcp_iss = arc4random(); /* wrong, but better than a constant */
|
||||
tcp_ccgen = 1;
|
||||
tcp_cleartaocache();
|
||||
|
||||
@ -1107,6 +1112,26 @@ tcp6_ctlinput(cmd, sa, d)
|
||||
}
|
||||
#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
|
||||
#define TCP_RNDISS_MAX 30000
|
||||
|
@ -758,7 +758,7 @@ tcp_connect(tp, nam, p)
|
||||
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);
|
||||
|
||||
/*
|
||||
@ -844,7 +844,7 @@ tcp6_connect(tp, nam, p)
|
||||
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);
|
||||
|
||||
/*
|
||||
|
@ -414,6 +414,7 @@ void tcp_rndiss_init __P((void));
|
||||
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 */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user