diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1996-09-20 22:53:14 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1996-09-20 22:53:14 +0000 |
commit | c922f1a659a0bb42a2e826c000568c540770e4af (patch) | |
tree | a4e78fa7dccb50511704fecbc4877af2064ffbcd | |
parent | 33a9681c867009363487e3d4d4201e9d7c4d25fb (diff) |
`solve' the syn bomb problem as well as currently known; add sysctl's for
SOMAXCONN (kern.somaxconn), SOMINCONN (kern.sominconn), and TCPTV_KEEP_INIT
(net.inet.tcp.keepinittime). when this is not enough (ie. overfull), start
doing tail drop, but slightly prefer the same port.
-rw-r--r-- | sys/kern/kern_sysctl.c | 7 | ||||
-rw-r--r-- | sys/kern/uipc_socket.c | 16 | ||||
-rw-r--r-- | sys/kern/uipc_socket2.c | 4 | ||||
-rw-r--r-- | sys/netinet/tcp_input.c | 63 | ||||
-rw-r--r-- | sys/netinet/tcp_usrreq.c | 8 | ||||
-rw-r--r-- | sys/netinet/tcp_var.h | 7 | ||||
-rw-r--r-- | sys/sys/sysctl.h | 8 |
7 files changed, 95 insertions, 18 deletions
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index ce090a7baf3..c3c20b170dd 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sysctl.c,v 1.11 1996/08/08 06:36:45 tholo Exp $ */ +/* $OpenBSD: kern_sysctl.c,v 1.12 1996/09/20 22:53:09 deraadt Exp $ */ /* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */ /*- @@ -204,6 +204,7 @@ kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) { int error, level, inthostid; extern char ostype[], osrelease[], osversion[], version[]; + extern int somaxconn, sominconn; /* all sysctl names at this level are terminal */ if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF)) @@ -289,6 +290,10 @@ kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) return (sysctl_rdint(oldp, oldlenp, newp, RAW_PART)); case KERN_NTPTIME: return (sysctl_ntptime(oldp, oldlenp)); + case KERN_SOMAXCONN: + return (sysctl_int(oldp, oldlenp, newp, newlen, &somaxconn)); + case KERN_SOMINCONN: + return (sysctl_int(oldp, oldlenp, newp, newlen, &sominconn)); default: return (EOPNOTSUPP); } diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 9cfe26d7f68..c71551fbfca 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket.c,v 1.6 1996/08/24 04:56:36 deraadt Exp $ */ +/* $OpenBSD: uipc_socket.c,v 1.7 1996/09/20 22:53:10 deraadt Exp $ */ /* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */ /* @@ -50,6 +50,12 @@ #include <sys/signalvar.h> #include <sys/resourcevar.h> +#ifndef SOMINCONN +#define SOMINCONN 80 +#endif /* SOMINCONN */ +int somaxconn = SOMAXCONN; +int sominconn = SOMINCONN; + /* * Socket operation routines. * These routines are called by the routines in @@ -131,9 +137,11 @@ solisten(so, backlog) } if (so->so_q == 0) so->so_options |= SO_ACCEPTCONN; - if (backlog < 0) - backlog = 0; - so->so_qlimit = min(backlog, SOMAXCONN); + if (backlog < 0 || backlog > somaxconn) + backlog = somaxconn; + if (backlog < sominconn) + backlog = sominconn; + so->so_qlimit = backlog; splx(s); return (0); } diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c index 66b22eb336e..92ab13de5e1 100644 --- a/sys/kern/uipc_socket2.c +++ b/sys/kern/uipc_socket2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket2.c,v 1.3 1996/08/24 04:56:37 deraadt Exp $ */ +/* $OpenBSD: uipc_socket2.c,v 1.4 1996/09/20 22:53:10 deraadt Exp $ */ /* $NetBSD: uipc_socket2.c,v 1.11 1996/02/04 02:17:55 christos Exp $ */ /* @@ -160,7 +160,7 @@ sonewconn1(head, connstatus) register struct socket *so; int soqueue = connstatus ? 1 : 0; - if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2) + if (head->so_qlen + head->so_q0len > head->so_qlimit * 3) return ((struct socket *)0); MALLOC(so, struct socket *, sizeof(*so), M_SOCKET, M_DONTWAIT); if (so == NULL) diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 8b7da3d6e30..0be9bed6e99 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_input.c,v 1.6 1996/08/07 06:36:26 tholo Exp $ */ +/* $OpenBSD: tcp_input.c,v 1.7 1996/09/20 22:53:11 deraadt Exp $ */ /* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */ /* @@ -66,6 +66,7 @@ int tcprexmtthresh = 3; struct tcpiphdr tcp_saveti; +int tcptv_keep_init = TCPTV_KEEP_INIT; extern u_long sb_max; @@ -232,6 +233,51 @@ present: } /* + * First check for a port-specific bomb. We do not want to drop half-opens + * for other ports if this is the only port being bombed. We only check + * the bottom 40 half open connections, to avoid wasting too much time. + * + * Or, otherwise it is more likely a generic syn bomb, so delete the oldest + * half-open connection. + */ +void +tcpdropoldhalfopen(avoidtp, port) + struct tcpcb *avoidtp; + u_int16_t port; +{ + register struct inpcb *inp; + register struct tcpcb *tp, *droptp = NULL; + int ncheck = 40; + int s; + + s = splnet(); + inp = tcbtable.inpt_queue.cqh_first; + if (inp) /* XXX */ + for (; inp != (struct inpcb *)&tcbtable.inpt_queue && --ncheck; + inp = inp->inp_queue.cqe_prev) { + if ((tp = (struct tcpcb *)inp->inp_ppcb) && + tp != avoidtp && + tp->t_state == TCPS_SYN_RECEIVED && + port == inp->inp_lport) { + tcp_close(tp); + goto done; + } + } + + inp = tcbtable.inpt_queue.cqh_first; + if (inp) /* XXX */ + for (; inp != (struct inpcb *)&tcbtable.inpt_queue; + inp = inp->inp_queue.cqe_prev) { + if ((tp = (struct tcpcb *)inp->inp_ppcb) && + tp != avoidtp && + tp->t_state == TCPS_SYN_RECEIVED) + break; + } +done: + splx(s); +} + +/* * TCP input routine, follows pages 65-76 of the * protocol specification dated September, 1981 very closely. */ @@ -386,9 +432,16 @@ findpcb: tcp_saveti = *ti; } if (so->so_options & SO_ACCEPTCONN) { - so = sonewconn(so, 0); - if (so == 0) - goto drop; + struct socket *so1; + + so1 = sonewconn(so, 0); + if (so1 == NULL) { + tcpdropoldhalfopen(tp, ti->ti_dport); + so1 = sonewconn(so, 0); + if (so1 == NULL) + goto drop; + } + so = so1; /* * This is ugly, but .... * @@ -630,7 +683,7 @@ findpcb: tcp_rcvseqinit(tp); tp->t_flags |= TF_ACKNOW; tp->t_state = TCPS_SYN_RECEIVED; - tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; + tp->t_timer[TCPT_KEEP] = tcptv_keep_init; dropsocket = 0; /* committed to socket */ tcpstat.tcps_accepts++; goto trimthenstep6; diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index a4e731ffc85..233403a8680 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_usrreq.c,v 1.6 1996/07/29 22:01:51 niklas Exp $ */ +/* $OpenBSD: tcp_usrreq.c,v 1.7 1996/09/20 22:53:12 deraadt Exp $ */ /* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */ /* @@ -72,6 +72,7 @@ * TCP protocol interface to socket abstraction. */ extern char *tcpstates[]; +extern int tcptv_keep_init; /* * Process a TCP user request for TCP tb. If this is a send request @@ -209,7 +210,7 @@ tcp_usrreq(so, req, m, nam, control) soisconnecting(so); tcpstat.tcps_connattempt++; tp->t_state = TCPS_SYN_SENT; - tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; + tp->t_timer[TCPT_KEEP] = tcptv_keep_init; tp->iss = tcp_iss; #ifdef TCP_COMPAT_42 tcp_iss += TCP_ISSINCR/2; @@ -574,6 +575,9 @@ tcp_sysctl(name, namelen, oldp, oldlenp, newp, newlen) case TCPCTL_RFC1323: return (sysctl_int(oldp, oldlenp, newp, newlen, &tcp_do_rfc1323)); + case TCPCTL_KEEPINITTIME: + return (sysctl_int(oldp, oldlenp, newp, newlen, + &tcptv_keep_init)); default: return (ENOPROTOOPT); diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index dde7c1b1e77..d7e84dd6201 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_var.h,v 1.4 1996/09/12 06:19:57 tholo Exp $ */ +/* $OpenBSD: tcp_var.h,v 1.5 1996/09/20 22:53:13 deraadt Exp $ */ /* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */ /* @@ -232,11 +232,13 @@ struct tcpstat { */ /* enable/disable RFC1323 timestamps/scaling */ #define TCPCTL_RFC1323 1 -#define TCPCTL_MAXID 2 +#define TCPCTL_KEEPINITTIME 2 +#define TCPCTL_MAXID 3 #define TCPCTL_NAMES { \ { 0, 0 }, \ { "rfc1323", CTLTYPE_INT }, \ + { "keepinittime", CTLTYPE_INT }, \ } #ifdef _KERNEL @@ -285,4 +287,5 @@ int tcp_sysctl __P((int *, u_int, void *, size_t *, void *, size_t)); int tcp_usrreq __P((struct socket *, int, struct mbuf *, struct mbuf *, struct mbuf *)); void tcp_xmit_timer __P((struct tcpcb *, int)); +void tcpdropoldhalfopen __P((struct tcpcb *, u_int16_t)); #endif diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index 2bbb2a6189f..7e985d36995 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sysctl.h,v 1.9 1996/08/11 20:35:12 niklas Exp $ */ +/* $OpenBSD: sysctl.h,v 1.10 1996/09/20 22:53:05 deraadt Exp $ */ /* $NetBSD: sysctl.h,v 1.16 1996/04/09 20:55:36 cgd Exp $ */ /* @@ -138,7 +138,9 @@ struct ctlname { #define KERN_NTPTIME 25 /* struct: extended-precision time */ #define KERN_TIMEX 26 /* struct: ntp timekeeping state */ #define KERN_OSVERSION 27 /* string: kernel build version */ -#define KERN_MAXID 28 /* number of valid kern ids */ +#define KERN_SOMAXCONN 28 /* int: listen queue maximum */ +#define KERN_SOMINCONN 29 /* int: half-open controllable param */ +#define KERN_MAXID 30 /* number of valid kern ids */ #define CTL_KERN_NAMES { \ { 0, 0 }, \ @@ -169,6 +171,8 @@ struct ctlname { { "ntptime", CTLTYPE_STRUCT }, \ { "timex", CTLTYPE_STRUCT }, \ { "osversion", CTLTYPE_STRING }, \ + { "somaxconn", CTLTYPE_INT }, \ + { "sominconn", CTLTYPE_INT }, \ } /* |