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
[-- Attachment #1 --] 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"]; [-- Attachment #2 --] -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.4 (FreeBSD) iD8DBQFG5FUd43LQWDWf0QIRAtWyAJ94JyjXtEY5Dl+9u/QN3KfOTsrQuACgirmD aHyP2ELbRkFzvCpev/9d1Zk= =4L3p -----END PGP SIGNATURE-----
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20070909201837.GA18107>
