Date: Wed, 23 Jul 1997 16:49:14 -0700 (PDT) From: leres@ee.lbl.gov (Craig Leres) To: FreeBSD-gnats-submit@FreeBSD.ORG Cc: leres@ee.lbl.gov, vern@ee.lbl.gov Subject: kern/4153: New tcp initial send sequence number code Message-ID: <199707232349.QAA19124@fun.ee.lbl.gov> Resent-Message-ID: <199707232350.QAA23797@hub.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 4153 >Category: kern >Synopsis: New tcp initial send sequence number code >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Class: change-request >Submitter-Id: current-users >Arrival-Date: Wed Jul 23 16:50:01 PDT 1997 >Last-Modified: >Originator: Craig Leres >Organization: Lawrence Berkeley National Laboratory >Release: FreeBSD 2.2.2-RELEASE i386 >Environment: >Description: The tcp iss number chosen by the 2.2.2-RELEASE kernel while an improvement over the constant increment version, it is still guessable. Although random() is used, the seed is not updated and so the pseudo random number sequence is essentially published. >How-To-Repeat: While we haven't actually written the test program that guesses the next iss, given access to the kernel source it is only an exercise. >Fix: The following context diffs use a 32 bit random number that is based on a seed that is not externally visible. (See the comments in tcp_new_iss() for a more detailed explaination.) While this version does technically violate the spec, it doesn't do so in a manner that will impact any current or future implementation. (We've been running a version of this code on our SunOS 4 systems since the early days of ip spoofing.) + rcsdiff -c tcp_input.c RCS file: RCS/tcp_input.c,v retrieving revision 1.2 diff -c -r1.2 tcp_input.c *** /tmp/,RCSt1019028 Wed Jul 23 16:46:16 1997 --- tcp_input.c Fri Jul 11 23:14:33 1997 *************** *** 272,278 **** --- 272,280 ---- int todrop, acked, ourfinisacked, needoutput = 0; struct in_addr laddr; int dropsocket = 0; + #ifndef LBL int iss = 0; + #endif u_long tiwin; struct tcpopt to; /* options in this segment */ struct rmxp_tao *taop; /* pointer to our TAO cache entry */ *************** *** 669,679 **** --- 671,685 ---- bzero(taop, sizeof(*taop)); } tcp_dooptions(tp, optp, optlen, ti, &to); + #ifdef LBL + tp->iss = tcp_new_iss(); + #else if (iss) tp->iss = iss; else tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/4; + #endif tp->irs = ti->ti_seq; tcp_sendseqinit(tp); tcp_rcvseqinit(tp); *************** *** 1070,1076 **** --- 1076,1084 ---- if (tiflags & TH_SYN && tp->t_state == TCPS_TIME_WAIT && SEQ_GT(ti->ti_seq, tp->rcv_nxt)) { + #ifndef LBL iss = tp->rcv_nxt + TCP_ISSINCR; + #endif tp = tcp_close(tp); goto findpcb; } + rcsdiff -c tcp_seq.h RCS file: RCS/tcp_seq.h,v retrieving revision 1.1 diff -c -r1.1 tcp_seq.h *** /tmp/,RCSt1019033 Wed Jul 23 16:46:16 1997 --- tcp_seq.h Fri Jul 11 22:54:06 1997 *************** *** 90,101 **** --- 90,104 ---- * If defined, the tcp_random18() macro should produce a * number in the range [0-0x3ffff] that is hard to predict. */ + #ifndef LBL + /* XXX See tcp_new_iss() in netniet/tcp_subr.c */ #ifndef tcp_random18 #define tcp_random18() ((random() >> 14) & 0x3ffff) #endif #define TCP_ISSINCR (122*1024 + tcp_random18()) extern tcp_seq tcp_iss; /* tcp initial send seq # */ + #endif #else #define TCP_ISSINCR (250*1024) /* increment for tcp_iss each second */ #endif /* KERNEL */ + rcsdiff -c tcp_subr.c RCS file: RCS/tcp_subr.c,v retrieving revision 1.1 diff -c -r1.1 tcp_subr.c *** /tmp/,RCSt1019038 Wed Jul 23 16:46:16 1997 --- tcp_subr.c Fri Jul 11 23:07:54 1997 *************** *** 46,51 **** --- 46,54 ---- #include <sys/socketvar.h> #include <sys/protosw.h> #include <sys/errno.h> + #ifdef LBL + #include <sys/vmmeter.h> /* source of randomness for tcp_new_iss() */ + #endif #include <net/route.h> #include <net/if.h> *************** *** 102,108 **** --- 105,113 ---- tcp_init() { + #ifndef LBL tcp_iss = random(); /* wrong, but better than a constant */ + #endif tcp_ccgen = 1; tcp_cleartaocache(); LIST_INIT(&tcb); *************** *** 113,118 **** --- 118,154 ---- if (max_linkhdr + sizeof(struct tcpiphdr) > MHLEN) panic("tcp_init"); } + + #ifdef LBL + tcp_seq + tcp_new_iss() + { + struct timeval now; + + /* + * choose a 'random' initial send sequence number that + * a) is unlikely to conflict with any other that we've + * recently used and (b) is hard for an adversary to + * guess. We use the low bits of the high res clock to + * gain some entropy then stick in some system counters + * that change rapidly & change on non-network activity + * to get some more then run the whole thing through kernrand + * so an attacker has to invert a non-linear function to start + * analyzing the pattern. Note that we're running this on + * a machine with at least microsecond clock resolution so + * the now.tv_usec term provides short term (<1s) variation & + * the v_swtch & v_syscall terms provide longer term variation. + * On a machine with a poor clock (10ms or worse resolution) + * the now.tv_usec should be replaced with something that + * varies substantially on a ~1ms (i.e., 1 packet time) scale. + * Also note that v_swtch & v_syscall are monotone increasing + * which is used to help with property (a) above. + */ + microtime(&now); + srandom((now.tv_usec << 10) ^ cnt.v_swtch ^ cnt.v_syscall); + return (random()); + } + #endif /* * Create template to be used to send tcp packets on a connection. + rcsdiff -c tcp_timer.c RCS file: RCS/tcp_timer.c,v retrieving revision 1.1 diff -c -r1.1 tcp_timer.c *** /tmp/,RCSt1019043 Wed Jul 23 16:46:16 1997 --- tcp_timer.c Fri Jul 11 23:18:45 1997 *************** *** 174,180 **** --- 174,182 ---- tpgone: ; } + #ifndef LBL tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ + #endif #ifdef TCP_COMPAT_42 if ((int)tcp_iss < 0) tcp_iss = TCP_ISSINCR; /* XXX */ + rcsdiff -c tcp_usrreq.c RCS file: RCS/tcp_usrreq.c,v retrieving revision 1.2 diff -c -r1.2 tcp_usrreq.c *** /tmp/,RCSt1019048 Wed Jul 23 16:46:16 1997 --- tcp_usrreq.c Fri Jul 11 23:17:45 1997 *************** *** 591,597 **** --- 591,601 ---- tcpstat.tcps_connattempt++; tp->t_state = TCPS_SYN_SENT; tp->t_timer[TCPT_KEEP] = tcp_keepinit; + #ifdef LBL + tp->iss = tcp_new_iss(); + #else tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2; + #endif tcp_sendseqinit(tp); /* + rcsdiff -c tcp_var.h RCS file: RCS/tcp_var.h,v retrieving revision 1.1 diff -c -r1.1 tcp_var.h *** /tmp/,RCSt1019053 Wed Jul 23 16:46:16 1997 --- tcp_var.h Fri Jul 11 22:53:56 1997 *************** *** 345,350 **** --- 345,353 ---- struct rmxp_tao * tcp_gettaocache __P((struct inpcb *)); void tcp_init __P((void)); + #ifdef LBL + tcp_seq tcp_new_iss __P((void)); + #endif void tcp_input __P((struct mbuf *, int)); void tcp_mss __P((struct tcpcb *, int)); int tcp_mssopt __P((struct tcpcb *)); >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199707232349.QAA19124>