Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 9 Sep 2007 22:18:37 +0200
From:      Matus Harvan <mharvan@inf.ethz.ch>
To:        freebsd-net@freebsd.org
Cc:        Max Laier <max@love2party.net>, Brooks Davis <brooks@freebsd.org>, mharvan@inf.ethz.ch
Subject:   UDP catchall
Message-ID:  <20070909201837.GA18107@inf.ethz.ch>

next in thread | raw e-mail | index | archive | help

--n8g4imXOkfNTN/H1
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Hello,

I am a Google Summer of Code student working on mtund, aka Magic
Tunnel Daemon aka Super Tunnel Daemon,
http://wiki.freebsd.org/SuperTunnelDaemon.

For mtund it would be useful to listen on all unused UDP ports,
allowing a client behind firewall to use any possible hole it could
find. To achieve this, the easiest way seems to be to allow a raw
IP/UDP socket to receive UDP traffic that no regular UDP socket
wants. In the kernel this means passing the mbuf from udp_input to
rip_input(). Upon receiving a packet, the user space program would
inspect the UDP header and create a UDP socket bound to the correct
local port and connected to the right remote port and address.

The user space usage would then look as follows:
	fd =3D socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
	recvfrom(fd, ...);
	/* parse the UDP header for the source and destination addresses */
	new_fd =3D socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
	bind(new_fd, ...);
	connect(new_fd, ...);

This catchall feature could be enabled/disabled via a sysctl variable,
net.inet.raw.udp_catchall. Furthermore, a rate limit could be used to
mitigate possible DoS misuse.

A simple testing program can be found under

http://p4web.freebsd.org/@md=3Dd&cd=3D//depot/projects/soc2007/mharvan-mtun=
d/sys.patches/test_catchall/&c=3Dxpc@//depot/projects/soc2007/mharvan-mtund=
/sys.patches/test_catchall/ucatchalld.c?ac=3D22

and a more complex example is the udp catchall plugin for mtund

http://p4web.freebsd.org/@md=3Dd&cd=3D//depot/projects/soc2007/mharvan-mtun=
d/mtund.src/&c=3DSM3@//depot/projects/soc2007/mharvan-mtund/mtund.src/plugi=
n_udp_catchall.c?ac=3D22

Matus

patch:
Index: udp_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/udp_usrreq.c,v
retrieving revision 1.216
diff -d -u -r1.216 udp_usrreq.c
--- udp_usrreq.c	10 Jul 2007 09:30:46 -0000	1.216
+++ udp_usrreq.c	6 Sep 2007 21:59:31 -0000
@@ -125,6 +125,15 @@
 SYSCTL_ULONG(_net_inet_udp, UDPCTL_RECVSPACE, recvspace, CTLFLAG_RW,
     &udp_recvspace, 0, "Maximum space for incoming UDP datagrams");
=20
+static int	udp_catchall =3D 0;
+SYSCTL_INT(_net_inet_raw, OID_AUTO, udp_catchall, CTLFLAG_RW | CTLFLAG_SEC=
URE,
+   &udp_catchall, 0, "Raw IP UDP sockets receive unclaimed UDP datagrams");
+
+static int	catchalllim =3D 5;
+SYSCTL_INT(_net_inet_udp, OID_AUTO, catchalllim, CTLFLAG_RW | CTLFLAG_SECU=
RE,
+   &catchalllim, 0,
+   "Rate limit on received UDP datagrams due to udp_catchall");
+
 struct inpcbhead	udb;		/* from udp_var.h */
 struct inpcbinfo	udbinfo;
=20
@@ -136,6 +145,11 @@
 SYSCTL_STRUCT(_net_inet_udp, UDPCTL_STATS, stats, CTLFLAG_RW, &udpstat,
     udpstat, "UDP statistics (struct udpstat, netinet/udp_var.h)");
=20
+static struct rate {
+  struct timeval	lasttime;
+  int		curpps;
+} catchallr;
+
 static void	udp_detach(struct socket *so);
 static int	udp_output(struct inpcb *, struct mbuf *, struct sockaddr *,
 		    struct mbuf *, struct thread *);
@@ -515,6 +529,35 @@
 	 */
 	inp =3D in_pcblookup_hash(&udbinfo, ip->ip_src, uh->uh_sport,
 	    ip->ip_dst, uh->uh_dport, 1, ifp);
+
+	/* catchall socket */
+	if (inp =3D=3D NULL && udp_catchall !=3D 0) {
+#ifdef DIAGNOSTIC
+		printf("IP UDP catchall active\n");
+		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(uh->uh_sport), dbuf, ntohs(uh->uh_dport));
+#endif
+
+		/* rate limiting */
+		if (catchalllim > 0)=20
+			if (ppsratecheck(&catchallr.lasttime,
+			    &catchallr.curpps, catchalllim)) {
+				rip_input(m, off);
+				INP_INFO_RUNLOCK(&udbinfo);
+				return;
+			}
+#ifdef DIAGNOSTIC
+			else
+			  printf("ppsratecheck limited "
+				    "udp_catchall\n");
+		else
+			printf("ppsratecheck limited udp_catchall\n");
+#endif
+	}
+
 	if (inp =3D=3D NULL) {
 		if (udp_log_in_vain) {
 			char buf[4*sizeof "123"];

--n8g4imXOkfNTN/H1
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.4 (FreeBSD)

iD8DBQFG5FUd43LQWDWf0QIRAtWyAJ94JyjXtEY5Dl+9u/QN3KfOTsrQuACgirmD
aHyP2ELbRkFzvCpev/9d1Zk=
=4L3p
-----END PGP SIGNATURE-----

--n8g4imXOkfNTN/H1--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20070909201837.GA18107>