Randomize the TCP initial sequence numbers more thoroughly.
Obtained from: OpenBSD Reviewed by: jesper, peter, -developers
This commit is contained in:
parent
e3ee8974e3
commit
f0a04f3f51
@ -1110,9 +1110,14 @@ tcp_input(m, off0, proto)
|
||||
tcp_dooptions(tp, optp, optlen, th, &to);
|
||||
if (iss)
|
||||
tp->iss = iss;
|
||||
else
|
||||
else {
|
||||
#ifdef TCP_COMPAT_42
|
||||
tcp_iss += TCP_ISSINCR/2;
|
||||
tp->iss = tcp_iss;
|
||||
tcp_iss += TCP_ISSINCR/4;
|
||||
#else
|
||||
tp->iss = tcp_rndiss_next();
|
||||
#endif /* TCP_COMPAT_42 */
|
||||
}
|
||||
tp->irs = th->th_seq;
|
||||
tcp_sendseqinit(tp);
|
||||
tcp_rcvseqinit(tp);
|
||||
@ -1643,7 +1648,11 @@ tcp_input(m, off0, proto)
|
||||
if (thflags & TH_SYN &&
|
||||
tp->t_state == TCPS_TIME_WAIT &&
|
||||
SEQ_GT(th->th_seq, tp->rcv_nxt)) {
|
||||
#ifdef TCP_COMPAT_42
|
||||
iss = tp->snd_nxt + TCP_ISSINCR;
|
||||
#else
|
||||
iss = tcp_rndiss_next();
|
||||
#endif /* TCP_COMPAT_42 */
|
||||
tp = tcp_close(tp);
|
||||
goto findpcb;
|
||||
}
|
||||
|
@ -1110,9 +1110,14 @@ tcp_input(m, off0, proto)
|
||||
tcp_dooptions(tp, optp, optlen, th, &to);
|
||||
if (iss)
|
||||
tp->iss = iss;
|
||||
else
|
||||
else {
|
||||
#ifdef TCP_COMPAT_42
|
||||
tcp_iss += TCP_ISSINCR/2;
|
||||
tp->iss = tcp_iss;
|
||||
tcp_iss += TCP_ISSINCR/4;
|
||||
#else
|
||||
tp->iss = tcp_rndiss_next();
|
||||
#endif /* TCP_COMPAT_42 */
|
||||
}
|
||||
tp->irs = th->th_seq;
|
||||
tcp_sendseqinit(tp);
|
||||
tcp_rcvseqinit(tp);
|
||||
@ -1643,7 +1648,11 @@ tcp_input(m, off0, proto)
|
||||
if (thflags & TH_SYN &&
|
||||
tp->t_state == TCPS_TIME_WAIT &&
|
||||
SEQ_GT(th->th_seq, tp->rcv_nxt)) {
|
||||
#ifdef TCP_COMPAT_42
|
||||
iss = tp->snd_nxt + TCP_ISSINCR;
|
||||
#else
|
||||
iss = tcp_rndiss_next();
|
||||
#endif /* TCP_COMPAT_42 */
|
||||
tp = tcp_close(tp);
|
||||
goto findpcb;
|
||||
}
|
||||
|
@ -81,6 +81,7 @@
|
||||
#ifdef _KERNEL
|
||||
extern tcp_cc tcp_ccgen; /* global connection count */
|
||||
|
||||
#ifdef TCP_COMPAT_42
|
||||
/*
|
||||
* Increment for tcp_iss each second.
|
||||
* This is designed to increment at the standard 250 KB/s,
|
||||
@ -96,6 +97,7 @@ extern tcp_cc tcp_ccgen; /* global connection count */
|
||||
#define TCP_ISSINCR (122*1024 + tcp_random18())
|
||||
|
||||
extern tcp_seq tcp_iss; /* tcp initial send seq # */
|
||||
#endif /* TCP_COMPAT_42 */
|
||||
#else
|
||||
#define TCP_ISSINCR (250*1024) /* increment for tcp_iss each second */
|
||||
#endif /* _KERNEL */
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/random.h>
|
||||
|
||||
#include <vm/vm_zone.h>
|
||||
|
||||
@ -181,7 +182,9 @@ tcp_init()
|
||||
{
|
||||
int hashsize;
|
||||
|
||||
tcp_iss = arc4random(); /* wrong, but better than a constant */
|
||||
#ifdef TCP_COMPAT_42
|
||||
tcp_iss = 1; /* wrong */
|
||||
#endif /* TCP_COMPAT_42 */
|
||||
tcp_ccgen = 1;
|
||||
tcp_cleartaocache();
|
||||
|
||||
@ -1100,6 +1103,63 @@ tcp6_ctlinput(cmd, sa, d)
|
||||
}
|
||||
#endif /* INET6 */
|
||||
|
||||
#define TCP_RNDISS_ROUNDS 16
|
||||
#define TCP_RNDISS_OUT 7200
|
||||
#define TCP_RNDISS_MAX 30000
|
||||
|
||||
u_int8_t tcp_rndiss_sbox[128];
|
||||
u_int16_t tcp_rndiss_msb;
|
||||
u_int16_t tcp_rndiss_cnt;
|
||||
long tcp_rndiss_reseed;
|
||||
|
||||
u_int16_t
|
||||
tcp_rndiss_encrypt(val)
|
||||
u_int16_t val;
|
||||
{
|
||||
u_int16_t sum = 0, i;
|
||||
|
||||
for (i = 0; i < TCP_RNDISS_ROUNDS; i++) {
|
||||
sum += 0x79b9;
|
||||
val ^= ((u_int16_t)tcp_rndiss_sbox[(val^sum) & 0x7f]) << 7;
|
||||
val = ((val & 0xff) << 7) | (val >> 8);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void
|
||||
tcp_rndiss_init()
|
||||
{
|
||||
struct timeval time;
|
||||
|
||||
getmicrotime(&time);
|
||||
read_random(tcp_rndiss_sbox, sizeof(tcp_rndiss_sbox));
|
||||
|
||||
tcp_rndiss_reseed = time.tv_sec + TCP_RNDISS_OUT;
|
||||
tcp_rndiss_msb = tcp_rndiss_msb == 0x8000 ? 0 : 0x8000;
|
||||
tcp_rndiss_cnt = 0;
|
||||
}
|
||||
|
||||
tcp_seq
|
||||
tcp_rndiss_next()
|
||||
{
|
||||
u_int16_t tmp;
|
||||
struct timeval time;
|
||||
|
||||
getmicrotime(&time);
|
||||
|
||||
if (tcp_rndiss_cnt >= TCP_RNDISS_MAX ||
|
||||
time.tv_sec > tcp_rndiss_reseed)
|
||||
tcp_rndiss_init();
|
||||
|
||||
read_random(&tmp, sizeof(tmp));
|
||||
|
||||
/* (tmp & 0x7fff) ensures a 32768 byte gap between ISS */
|
||||
return ((tcp_rndiss_encrypt(tcp_rndiss_cnt++) | tcp_rndiss_msb) <<16) |
|
||||
(tmp & 0x7fff);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* When a source quench is received, close congestion window
|
||||
* to one segment. We will gradually open it again as we proceed.
|
||||
|
@ -132,8 +132,8 @@ tcp_slowtimo()
|
||||
|
||||
tcp_maxidle = tcp_keepcnt * tcp_keepintvl;
|
||||
|
||||
tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */
|
||||
#ifdef TCP_COMPAT_42
|
||||
tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */
|
||||
if ((int)tcp_iss < 0)
|
||||
tcp_iss = TCP_ISSINCR; /* XXX */
|
||||
#endif
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/random.h>
|
||||
|
||||
#include <vm/vm_zone.h>
|
||||
|
||||
@ -181,7 +182,9 @@ tcp_init()
|
||||
{
|
||||
int hashsize;
|
||||
|
||||
tcp_iss = arc4random(); /* wrong, but better than a constant */
|
||||
#ifdef TCP_COMPAT_42
|
||||
tcp_iss = 1; /* wrong */
|
||||
#endif /* TCP_COMPAT_42 */
|
||||
tcp_ccgen = 1;
|
||||
tcp_cleartaocache();
|
||||
|
||||
@ -1100,6 +1103,63 @@ tcp6_ctlinput(cmd, sa, d)
|
||||
}
|
||||
#endif /* INET6 */
|
||||
|
||||
#define TCP_RNDISS_ROUNDS 16
|
||||
#define TCP_RNDISS_OUT 7200
|
||||
#define TCP_RNDISS_MAX 30000
|
||||
|
||||
u_int8_t tcp_rndiss_sbox[128];
|
||||
u_int16_t tcp_rndiss_msb;
|
||||
u_int16_t tcp_rndiss_cnt;
|
||||
long tcp_rndiss_reseed;
|
||||
|
||||
u_int16_t
|
||||
tcp_rndiss_encrypt(val)
|
||||
u_int16_t val;
|
||||
{
|
||||
u_int16_t sum = 0, i;
|
||||
|
||||
for (i = 0; i < TCP_RNDISS_ROUNDS; i++) {
|
||||
sum += 0x79b9;
|
||||
val ^= ((u_int16_t)tcp_rndiss_sbox[(val^sum) & 0x7f]) << 7;
|
||||
val = ((val & 0xff) << 7) | (val >> 8);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void
|
||||
tcp_rndiss_init()
|
||||
{
|
||||
struct timeval time;
|
||||
|
||||
getmicrotime(&time);
|
||||
read_random(tcp_rndiss_sbox, sizeof(tcp_rndiss_sbox));
|
||||
|
||||
tcp_rndiss_reseed = time.tv_sec + TCP_RNDISS_OUT;
|
||||
tcp_rndiss_msb = tcp_rndiss_msb == 0x8000 ? 0 : 0x8000;
|
||||
tcp_rndiss_cnt = 0;
|
||||
}
|
||||
|
||||
tcp_seq
|
||||
tcp_rndiss_next()
|
||||
{
|
||||
u_int16_t tmp;
|
||||
struct timeval time;
|
||||
|
||||
getmicrotime(&time);
|
||||
|
||||
if (tcp_rndiss_cnt >= TCP_RNDISS_MAX ||
|
||||
time.tv_sec > tcp_rndiss_reseed)
|
||||
tcp_rndiss_init();
|
||||
|
||||
read_random(&tmp, sizeof(tmp));
|
||||
|
||||
/* (tmp & 0x7fff) ensures a 32768 byte gap between ISS */
|
||||
return ((tcp_rndiss_encrypt(tcp_rndiss_cnt++) | tcp_rndiss_msb) <<16) |
|
||||
(tmp & 0x7fff);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* When a source quench is received, close congestion window
|
||||
* to one segment. We will gradually open it again as we proceed.
|
||||
|
@ -761,7 +761,12 @@ 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_iss; tcp_iss += TCP_ISSINCR/2;
|
||||
#ifdef TCP_COMPAT_42
|
||||
tp->iss = tcp_iss;
|
||||
tcp_iss += TCP_ISSINCR/2;
|
||||
#else /* TCP_COMPAT_42 */
|
||||
tp->iss = tcp_rndiss_next();
|
||||
#endif /* !TCP_COMPAT_42 */
|
||||
tcp_sendseqinit(tp);
|
||||
|
||||
/*
|
||||
@ -853,7 +858,11 @@ 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);
|
||||
#ifdef TCP_COMPAT_42
|
||||
tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
|
||||
#else
|
||||
tp->iss = tcp_rndiss_next();
|
||||
#endif /* TCP_COMPAT_42 */
|
||||
tcp_sendseqinit(tp);
|
||||
|
||||
/*
|
||||
|
@ -409,6 +409,10 @@ void tcp_trace __P((int, int, struct tcpcb *, void *, struct tcphdr *,
|
||||
extern struct pr_usrreqs tcp_usrreqs;
|
||||
extern u_long tcp_sendspace;
|
||||
extern u_long tcp_recvspace;
|
||||
void tcp_rndiss_init __P((void));
|
||||
tcp_seq tcp_rndiss_next __P((void));
|
||||
u_int16_t
|
||||
tcp_rndiss_encrypt __P((u_int16_t));
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user