Skip site navigation (1)Skip section navigation (2)
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>