From owner-freebsd-net@FreeBSD.ORG Tue May 11 10:54:38 2004 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id B87E816A4CE for ; Tue, 11 May 2004 10:54:38 -0700 (PDT) Received: from cheer.mahoroba.org (flets19-146.kamome.or.jp [218.45.19.146]) by mx1.FreeBSD.org (Postfix) with ESMTP id 6959043D45 for ; Tue, 11 May 2004 10:54:36 -0700 (PDT) (envelope-from ume@FreeBSD.org) Received: from lyrics.mahoroba.org (IDENT:yYPuMMLHJ+df/Cy/4JfCVGBI9cKl2kaUyXJhGzpzkHW3AnfZQDkQ3iAgznXcj24g@lyrics.mahoroba.org [IPv6:3ffe:501:185b:8010:280:88ff:fe03:4841]) (user=ume mech=CRAM-MD5 bits=0)i4BHr2hD084893 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 12 May 2004 02:53:06 +0900 (JST) (envelope-from ume@FreeBSD.org) Date: Wed, 12 May 2004 02:53:02 +0900 Message-ID: From: Hajimu UMEMOTO To: Lukasz Stelmach In-Reply-To: <20040511160734.GA66419@tygrys.k.telmark.waw.pl> References: <20040511160734.GA66419@tygrys.k.telmark.waw.pl> User-Agent: xcite1.38> Wanderlust/2.11.3 (Wonderwall) SEMI/1.14.6 (Maruoka) FLIM/1.14.6 (Marutamachi) APEL/10.6 Emacs/21.3 (i386--freebsd) MULE/5.0 (SAKAKI) X-Operating-System: FreeBSD 5.2-CURRENT MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Content-Type: multipart/mixed; boundary="Multipart_Wed_May_12_02:53:02_2004-1" X-Virus-Scanned: by amavisd-new X-Virus-Status: Clean X-Spam-Status: No, hits=-4.7 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=2.63 X-Spam-Checker-Version: SpamAssassin 2.63 (2004-01-11) on cheer.mahoroba.org cc: freebsd-net@freebsd.org cc: SUZUKI Shinsuke Subject: Re: if_stf bug/feature X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 11 May 2004 17:54:38 -0000 --Multipart_Wed_May_12_02:53:02_2004-1 Content-Type: text/plain; charset=US-ASCII Hi, >>>>> On Tue, 11 May 2004 18:07:34 +0200 >>>>> Lukasz Stelmach said: Lukasz> In one of my previous letters I have mentioned that i use 4.9-RCsomething Lukasz> and unfortunately this is my only FreeBSD. I am also afraid :-( that Lukasz> i don't have enough spare time neither. But please send the patch and Lukasz> I will *try* to look at it if you don't mind. I knew that you are using 4.X from your post to stable@. I attach my candidate patch for 4-STABLE into this mail. Suzuki-san mentioned RFC3056. However, though 5-CURRENT checks if an address is not RFC1918 address, 4-STABLE version of if_stf doesn't check RFC1918 address. I included this check into my patch. It makes NAT thing more difficult, though. A friend of mine tested this patch on his 4-STABLE box. Sincerely, --Multipart_Wed_May_12_02:53:02_2004-1 Content-Type: application/octet-stream; type=patch Content-Disposition: attachment; filename="if_stf.c-nat-4s.diff" Content-Transfer-Encoding: 7bit Index: share/man/man4/stf.4 diff -u share/man/man4/stf.4.orig share/man/man4/stf.4 --- share/man/man4/stf.4.orig Wed Sep 18 01:53:04 2002 +++ share/man/man4/stf.4 Wed May 12 00:39:09 2004 @@ -175,6 +175,16 @@ Note, however, there are other security risks exist. If you wish to use the configuration, you must not advertise your 6to4 address to others. +.Pp +You can configure to use 6to4 from behind NAT by setting the +.Xr sysctl 8 +variable +.Va net.link.stf.no_addr4check +to 1 with support of your NAT box. +If you are directly connected to the Internet, you shouldn't +chenge the value of +.Va net.link.stf.no_addr4check . +This is only hack to use 6to4 from within a NAT. .\" .Sh EXAMPLES Note that Index: sys/net/if_stf.c diff -u -p sys/net/if_stf.c.orig sys/net/if_stf.c --- sys/net/if_stf.c.orig Tue Feb 4 03:55:47 2003 +++ sys/net/if_stf.c Wed May 12 02:43:17 2004 @@ -85,6 +85,7 @@ #include #include #include +#include #include #include @@ -147,6 +148,7 @@ static int stf_encapcheck __P((const str static struct in6_ifaddr *stf_getsrcifa6 __P((struct ifnet *)); static int stf_output __P((struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *)); +static int isrfc1918addr __P((struct in_addr *)); static int stf_checkaddr4 __P((struct stf_softc *, struct in_addr *, struct ifnet *)); static int stf_checkaddr6 __P((struct stf_softc *, struct in6_addr *, @@ -154,6 +156,13 @@ static int stf_checkaddr6 __P((struct st static void stf_rtrequest __P((int, struct rtentry *, struct rt_addrinfo *)); static int stf_ioctl __P((struct ifnet *, u_long, caddr_t)); +SYSCTL_DECL(_net_link); +SYSCTL_NODE(_net_link, IFT_STF, stf, CTLFLAG_RW, 0, "6to4 Interface"); + +static int no_addr4check = 0; +SYSCTL_INT(_net_link_stf, OID_AUTO, no_addr4check, CTLFLAG_RW, + &no_addr4check, 0, "Skip outer IPv4 address"); + static int stfmodevent(mod, type, data) module_t mod; @@ -261,9 +270,17 @@ stf_encapcheck(m, off, proto, arg) * local 6to4 address. * success on: dst = 10.1.1.1, ia6->ia_addr = 2002:0a01:0101:... */ - if (bcmp(GET_V4(&ia6->ia_addr.sin6_addr), &ip.ip_dst, - sizeof(ip.ip_dst)) != 0) - return 0; + if (no_addr4check) { + struct ifnet *tif; + + INADDR_TO_IFP(ip.ip_dst, tif); + if (!tif) + return 0; + } else { + if (bcmp(GET_V4(&ia6->ia_addr.sin6_addr), &ip.ip_dst, + sizeof(ip.ip_dst)) != 0) + return 0; + } /* * check if IPv4 src matches the IPv4 address derived from the @@ -301,12 +318,14 @@ stf_getsrcifa6(ifp) if (!IN6_IS_ADDR_6TO4(&sin6->sin6_addr)) continue; - bcopy(GET_V4(&sin6->sin6_addr), &in, sizeof(in)); - LIST_FOREACH(ia4, INADDR_HASH(in.s_addr), ia_hash) - if (ia4->ia_addr.sin_addr.s_addr == in.s_addr) - break; - if (ia4 == NULL) - continue; + if (!no_addr4check) { + bcopy(GET_V4(&sin6->sin6_addr), &in, sizeof(in)); + LIST_FOREACH(ia4, INADDR_HASH(in.s_addr), ia_hash) + if (ia4->ia_addr.sin_addr.s_addr == in.s_addr) + break; + if (ia4 == NULL) + continue; + } return (struct in6_ifaddr *)ia; } @@ -404,8 +423,9 @@ stf_output(ifp, m, dst, rt) bzero(ip, sizeof(*ip)); - bcopy(GET_V4(&((struct sockaddr_in6 *)&ia6->ia_addr)->sin6_addr), - &ip->ip_src, sizeof(ip->ip_src)); + if (!no_addr4check) + bcopy(GET_V4(&((struct sockaddr_in6 *)&ia6->ia_addr)->sin6_addr), + &ip->ip_src, sizeof(ip->ip_src)); bcopy(in4, &ip->ip_dst, sizeof(ip->ip_dst)); ip->ip_p = IPPROTO_IPV6; ip->ip_ttl = ip_stf_ttl; @@ -440,6 +460,22 @@ stf_output(ifp, m, dst, rt) } static int +isrfc1918addr(in) + struct in_addr *in; +{ + /* + * returns 1 if private address range: + * 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 + */ + if ((ntohl(in->s_addr) & 0xff000000) >> 24 == 10 || + (ntohl(in->s_addr) & 0xfff00000) >> 16 == 172 * 256 + 16 || + (ntohl(in->s_addr) & 0xffff0000) >> 16 == 192 * 256 + 168) + return 1; + + return 0; +} + +static int stf_checkaddr4(sc, in, inifp) struct stf_softc *sc; struct in_addr *in; @@ -508,8 +544,20 @@ stf_checkaddr6(sc, in6, inifp) /* * check 6to4 addresses */ - if (IN6_IS_ADDR_6TO4(in6)) - return stf_checkaddr4(sc, GET_V4(in6), inifp); + if (IN6_IS_ADDR_6TO4(in6)) { + struct in_addr in4; + + bcopy(GET_V4(in6), &in4, sizeof(in4)); + + /* + * reject packets with private address range. + * (requirement from RFC3056 section 2 1st paragraph) + */ + if (isrfc1918addr(&in4)) + return -1; + + return stf_checkaddr4(sc, &in4, inifp); + } /* * reject anything that look suspicious. the test is implemented @@ -572,6 +620,18 @@ in_stf_input(m, va_alist) return; } + /* + * Skip RFC1918 check against dest address to allow incoming + * packets with private address for dest. Though it may + * breasks the requirement from RFC3056 section 2 1st + * paragraph, it helps for 6to4 over NAT. + */ + if ((!no_addr4check && isrfc1918addr(&ip->ip_dst)) || + isrfc1918addr(&ip->ip_src)) { + m_freem(m); + return; + } + otos = ip->ip_tos; m_adj(m, off); @@ -668,6 +728,7 @@ stf_ioctl(ifp, cmd, data) struct ifaddr *ifa; struct ifreq *ifr; struct sockaddr_in6 *sin6; + struct in_addr addr; int error; error = 0; @@ -679,11 +740,18 @@ stf_ioctl(ifp, cmd, data) break; } sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; - if (IN6_IS_ADDR_6TO4(&sin6->sin6_addr)) { - ifa->ifa_rtrequest = stf_rtrequest; - ifp->if_flags |= IFF_UP; - } else + if (!IN6_IS_ADDR_6TO4(&sin6->sin6_addr)) { + error = EINVAL; + break; + } + bcopy(GET_V4(&sin6->sin6_addr), &addr, sizeof(addr)); + if (isrfc1918addr(&addr)) { error = EINVAL; + break; + } + + ifa->ifa_rtrequest = stf_rtrequest; + ifp->if_flags |= IFF_UP; break; case SIOCADDMULTI: --Multipart_Wed_May_12_02:53:02_2004-1 Content-Type: text/plain; charset=US-ASCII -- Hajimu UMEMOTO @ Internet Mutual Aid Society Yokohama, Japan ume@mahoroba.org ume@{,jp.}FreeBSD.org http://www.imasy.org/~ume/ --Multipart_Wed_May_12_02:53:02_2004-1--