UDP catchall

Matus Harvan mharvan at inf.ethz.ch
Sun Sep 9 13:23:56 PDT 2007


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 = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
	recvfrom(fd, ...);
	/* parse the UDP header for the source and destination addresses */
	new_fd = 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=d&cd=//depot/projects/soc2007/mharvan-mtund/sys.patches/test_catchall/&c=xpc@//depot/projects/soc2007/mharvan-mtund/sys.patches/test_catchall/ucatchalld.c?ac=22

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

http://p4web.freebsd.org/@md=d&cd=//depot/projects/soc2007/mharvan-mtund/mtund.src/&c=SM3@//depot/projects/soc2007/mharvan-mtund/mtund.src/plugin_udp_catchall.c?ac=22

Matus

patch:
Index: udp_usrreq.c
===================================================================
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");
 
+static int	udp_catchall = 0;
+SYSCTL_INT(_net_inet_raw, OID_AUTO, udp_catchall, CTLFLAG_RW | CTLFLAG_SECURE,
+   &udp_catchall, 0, "Raw IP UDP sockets receive unclaimed UDP datagrams");
+
+static int	catchalllim = 5;
+SYSCTL_INT(_net_inet_udp, OID_AUTO, catchalllim, CTLFLAG_RW | CTLFLAG_SECURE,
+   &catchalllim, 0,
+   "Rate limit on received UDP datagrams due to udp_catchall");
+
 struct inpcbhead	udb;		/* from udp_var.h */
 struct inpcbinfo	udbinfo;
 
@@ -136,6 +145,11 @@
 SYSCTL_STRUCT(_net_inet_udp, UDPCTL_STATS, stats, CTLFLAG_RW, &udpstat,
     udpstat, "UDP statistics (struct udpstat, netinet/udp_var.h)");
 
+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 = in_pcblookup_hash(&udbinfo, ip->ip_src, uh->uh_sport,
 	    ip->ip_dst, uh->uh_dport, 1, ifp);
+
+	/* catchall socket */
+	if (inp == NULL && udp_catchall != 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) 
+			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 == NULL) {
 		if (udp_log_in_vain) {
 			char buf[4*sizeof "123"];
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 187 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-net/attachments/20070909/6e9ec62a/attachment.pgp


More information about the freebsd-net mailing list