Date: Fri, 26 Oct 2007 17:52:06 +0200 From: Matus Harvan <mharvan@inf.ethz.ch> To: freebsd-net@freebsd.org Cc: Max Laier <max@love2party.net>, Brooks Davis <brooks@freebsd.org> Subject: Re: TCP listenall Message-ID: <20071026155206.GH1049@styx.ethz.ch> In-Reply-To: <20070909204148.GB18107@inf.ethz.ch> References: <20070909204148.GB18107@inf.ethz.ch>
next in thread | previous in thread | raw e-mail | index | archive | help
--wj9ZLJVQDRFjGSdK Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Hi, =20 I was wondering if I could get some feedback about the patch and whether others think it could be committed. A slightly update version of the patch is at the end of this email. =20 Matus On Sun, Sep 09, 2007 at 10:41:48PM +0200, Matus Harvan wrote: > Hello, >=20 > I am a Google Summer of Code student working on mtund, aka Magic > Tunnel Daemon aka Super Tunnel Daemon, > http://wiki.freebsd.org/SuperTunnelDaemon. >=20 > For mtund it would be useful to listen on all unused TCP ports, > allowing a client behind firewall to use any possible hole it could > find. To achieve this I would suggest the patch below. It would add a > socket option TCP_LISTENALL. This clearly could only be set on one > socket. When activated, the global variable inp_tlistenall would be > used to assign traffic to unused TCP ports to that socket. In > particular, the changed code in tcp_input() would be used twice - once > for the SYN packet (1st packet) and once for the ACK packet (3rd > packet). inp_tlistenall is protected by the INP_INFO lock on tcbinfo > in all places. >=20 > The patch also includes rate limiting to mitigate possible DoS > misuse. With listenall enabled, a portscan becomes a syn > flood. However, as there are already mechanisms to protect against a > syn flood attack, such as syncache and syncookies, the rate limit > might be left out. The disadvanatage of the rate limit is that a > portscan becomes a DoS against the listenall socket. >=20 > A testing program is available in perforce: > http://p4web.freebsd.org/@md=3Dd&cd=3D//depot/projects/soc2007/mharvan-mt= und/sys.patches/test_catchall/&c=3Dxpc@//depot/projects/soc2007/mharvan-mtu= nd/sys.patches/test_catchall/tcatchalld.c?ac=3D22 >=20 > Note that the tcp listenall feature would be usefull to other programs > beyond mtund, i.e., a modified ssh daemon for people who won't be able > to run mtund, but will be able to run ssh. >=20 > Matus >=20 patch: Index: netinet/tcp.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /home/ncvs/src/sys/netinet/tcp.h,v retrieving revision 1.40 diff -u -r1.40 tcp.h --- netinet/tcp.h 25 May 2007 21:28:49 -0000 1.40 +++ netinet/tcp.h 26 Oct 2007 15:41:17 -0000 @@ -147,6 +147,7 @@ #define TCP_NOOPT 0x08 /* don't use TCP options */ #define TCP_MD5SIG 0x10 /* use MD5 digests (RFC2385) */ #define TCP_INFO 0x20 /* retrieve tcp_info structure */ +#define TCP_LISTENALL 0x40 /* listen on all unused TCP ports */ =20 #define TCPI_OPT_TIMESTAMPS 0x01 #define TCPI_OPT_SACK 0x02 Index: netinet/tcp_input.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /home/ncvs/src/sys/netinet/tcp_input.c,v retrieving revision 1.370 diff -u -r1.370 tcp_input.c --- netinet/tcp_input.c 7 Oct 2007 20:44:23 -0000 1.370 +++ netinet/tcp_input.c 26 Oct 2007 15:41:17 -0000 @@ -146,9 +146,15 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, recvbuf_max, CTLFLAG_RW, &tcp_autorcvbuf_max, 0, "Max size of automatic receive buffer"); =20 +static int listenalllim =3D 5; +SYSCTL_INT(_net_inet_tcp, OID_AUTO, listenalllim, CTLFLAG_RW | CTLFLAG_SEC= URE, + &listenalllim, 0, + "Rate limit on sockets created by the TCP_LISTENALL socket"); + struct inpcbhead tcb; #define tcb6 tcb /* for KAME src sync over BSD*'s */ struct inpcbinfo tcbinfo; +struct inpcb *inp_tlistenall; /* listening on all unused TCP ports */ =20 static void tcp_dooptions(struct tcpopt *, u_char *, int, int); static void tcp_do_segment(struct mbuf *, struct tcphdr *, @@ -260,6 +266,11 @@ struct tcphdr tcp_savetcp; short ostate =3D 0; #endif + static struct rate { + struct timeval lasttime; + int curpps; + } listenallr; + =20 #ifdef INET6 isipv6 =3D (mtod(m, struct ip *)->ip_v =3D=3D 6) ? 1 : 0; @@ -448,6 +459,36 @@ ip->ip_dst, th->th_dport, INPLOOKUP_WILDCARD, m->m_pkthdr.rcvif); + } + + /* listenall socket */ + if ((inp =3D=3D NULL) && (inp_tlistenall !=3D NULL)) { +#ifdef DIAGNOSTIC + printf("listenall socket used (0x%x)\n", + (unsigned int)inp_tlistenall); + char dbuf[INET_ADDRSTRLEN], sbuf[INET_ADDRSTRLEN]; + strcpy(dbuf, inet_ntoa(ip->ip_dst)); + strcpy(sbuf, inet_ntoa(ip->ip_src)); + printf("\tip_src: %s, sport: %hu\n\tip_dst: %s, dport: %hu\n", + sbuf, ntohs(th->th_sport), dbuf, ntohs(th->th_dport)); +#endif + /* do rate limiting for SYN packets */ + if (thflags & TH_SYN) { + if (listenalllim > 0)=20 + if (ppsratecheck(&listenallr.lasttime, + &listenallr.curpps, listenalllim)) + inp =3D inp_tlistenall; +#ifdef DIAGNOSTIC + else + printf("ppsratecheck limited " + "tcp_listenall\n"); +#endif +#ifdef DIAGNOSTIC + else + printf("ppsratecheck limited tcp_listenall\n"); +#endif + } else + inp =3D inp_tlistenall; } =20 /* Index: netinet/tcp_subr.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /home/ncvs/src/sys/netinet/tcp_subr.c,v retrieving revision 1.300 diff -u -r1.300 tcp_subr.c --- netinet/tcp_subr.c 7 Oct 2007 20:44:24 -0000 1.300 +++ netinet/tcp_subr.c 26 Oct 2007 15:41:17 -0000 @@ -266,6 +266,7 @@ tcp_rexmit_slop =3D TCPTV_CPU_VAR; tcp_inflight_rttthresh =3D TCPTV_INFLIGHT_RTTTHRESH; tcp_finwait2_timeout =3D TCPTV_FINWAIT2_TIMEOUT; + inp_tlistenall =3D NULL; =20 INP_INFO_LOCK_INIT(&tcbinfo, "tcp"); LIST_INIT(&tcb); Index: netinet/tcp_usrreq.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /home/ncvs/src/sys/netinet/tcp_usrreq.c,v retrieving revision 1.163 diff -u -r1.163 tcp_usrreq.c --- netinet/tcp_usrreq.c 7 Oct 2007 20:44:24 -0000 1.163 +++ netinet/tcp_usrreq.c 26 Oct 2007 15:41:17 -0000 @@ -50,6 +50,7 @@ #endif /* INET6 */ #include <sys/socket.h> #include <sys/socketvar.h> +#include <sys/priv.h> #include <sys/protosw.h> #include <sys/proc.h> #include <sys/jail.h> @@ -164,6 +165,13 @@ KASSERT(so->so_pcb =3D=3D inp, ("tcp_detach: so_pcb !=3D inp")); KASSERT(inp->inp_socket =3D=3D so, ("tcp_detach: inp_socket !=3D so")); =20 + if (inp =3D=3D inp_tlistenall) { +#ifdef DIAGNOSTIC + printf("deactivating TCP_LISTENALL - socket closed\n"); +#endif + inp_tlistenall =3D NULL; + } + tp =3D intotcpcb(inp); =20 if (inp->inp_vflag & INP_TIMEWAIT) { @@ -1340,6 +1348,29 @@ error =3D EINVAL; break; =20 + case TCP_LISTENALL: + error =3D sooptcopyin(sopt, &optval, sizeof optval, + sizeof optval); + if (error) + break; + + priv_check(curthread, + PRIV_NETINET_TCP_LISTENALL); + if (error !=3D 0) + break; + + if (optval > 0) /* enable LISTENALL */ + if (inp_tlistenall =3D=3D NULL) + inp_tlistenall =3D inp; + else + error =3D EBUSY; + + else /* disable LISTENALL */ + if (inp_tlistenall =3D=3D inp) + inp_tlistenall =3D NULL; + + break; + default: error =3D ENOPROTOOPT; break; @@ -1373,6 +1404,13 @@ case TCP_INFO: tcp_fill_info(tp, &ti); error =3D sooptcopyout(sopt, &ti, sizeof ti); + break; + case TCP_LISTENALL: + if (inp =3D=3D inp_tlistenall) =20 + optval =3D 1; + else + optval =3D 0; + error =3D sooptcopyout(sopt, &optval, sizeof optval); break; default: error =3D ENOPROTOOPT; Index: netinet/tcp_var.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /home/ncvs/src/sys/netinet/tcp_var.h,v retrieving revision 1.157 diff -u -r1.157 tcp_var.h --- netinet/tcp_var.h 24 Sep 2007 05:26:24 -0000 1.157 +++ netinet/tcp_var.h 26 Oct 2007 15:41:17 -0000 @@ -493,6 +493,7 @@ =20 extern struct inpcbhead tcb; /* head of queue of active tcpcb's */ extern struct inpcbinfo tcbinfo; +extern struct inpcb *inp_tlistenall; /* listening on all unused TCP ports= */ extern struct tcpstat tcpstat; /* tcp statistics */ extern int tcp_log_in_vain; extern int tcp_mssdflt; /* XXX */ Index: sys/priv.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /home/ncvs/src/sys/sys/priv.h,v retrieving revision 1.15 diff -u -r1.15 priv.h --- sys/priv.h 18 Jun 2007 07:54:27 -0000 1.15 +++ sys/priv.h 26 Oct 2007 15:41:19 -0000 @@ -374,6 +374,7 @@ #define PRIV_NETINET_ALIFETIME6 502 /* Administer IPv6 address lifetimes. = */ #define PRIV_NETINET_IPSEC 503 /* Administer IPSEC. */ #define PRIV_NETINET_REUSEPORT 504 /* Allow [rapid] port/address reuse. */ +#define PRIV_NETINET_TCP_LISTENALL 505 /* Allow setting TCP_LISTENALL */ =20 /* * IPX/SPX privileges. --wj9ZLJVQDRFjGSdK Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.4 (FreeBSD) iD8DBQFHIg0l43LQWDWf0QIRArK6AKCPwCaBSdl+4/+11m264zXOYr5H5QCgjqb7 xjRQW7TnlNcNi0JiFLWbrU4= =wD+w -----END PGP SIGNATURE----- --wj9ZLJVQDRFjGSdK--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20071026155206.GH1049>