From owner-freebsd-net@FreeBSD.ORG Wed Sep 5 13:10:02 2012 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 18DF3106564A for ; Wed, 5 Sep 2012 13:10:02 +0000 (UTC) (envelope-from longwitz@incore.de) Received: from dss.incore.de (dss.incore.de [195.145.1.138]) by mx1.freebsd.org (Postfix) with ESMTP id AC49E8FC14 for ; Wed, 5 Sep 2012 13:10:01 +0000 (UTC) Received: from inetmail.dmz (inetmail.dmz [10.3.0.3]) by dss.incore.de (Postfix) with ESMTP id 941135C68A for ; Wed, 5 Sep 2012 15:02:22 +0200 (CEST) X-Virus-Scanned: amavisd-new at incore.de Received: from dss.incore.de ([10.3.0.3]) by inetmail.dmz (inetmail.dmz [10.3.0.3]) (amavisd-new, port 10024) with LMTP id sGqG7dBe3UAv for ; Wed, 5 Sep 2012 15:02:21 +0200 (CEST) Received: from mail.incore (fwintern.dmz [10.0.0.253]) by dss.incore.de (Postfix) with ESMTP id 28A125C688 for ; Wed, 5 Sep 2012 15:02:21 +0200 (CEST) Received: from bsdlo.incore (bsdlo.incore [192.168.0.84]) by mail.incore (Postfix) with ESMTP id 22C3545084 for ; Wed, 5 Sep 2012 15:02:21 +0200 (CEST) Message-ID: <50474D5C.4020003@incore.de> Date: Wed, 05 Sep 2012 15:02:20 +0200 From: Andreas Longwitz User-Agent: Thunderbird 2.0.0.19 (X11/20090113) MIME-Version: 1.0 To: freebsd-net@freebsd.org Content-Type: text/plain; charset=ISO-8859-15 Content-Transfer-Encoding: 8bit Subject: Support for IPSec VPN's: some patches for netipsec/key.c X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 05 Sep 2012 13:10:02 -0000 Hi, as continuation of http://lists.freebsd.org/pipermail/freebsd-stable/2012-April/067307.html I like to describe what I have done to get smartphones with IPSec VPN's working with a FreeBSD 8.3 server. The clients are IPhones with Cisco IPSec (authentication_method xauth_rsa_server in tunnel mode) and Androids with L2TP over IPSec (authentication_method rsasig in transport mode). On the server I have FreeBSD 8.3 with NAT-T support and the ports ipsec-tools-0.8.0_2 and mpd-5.5. To filter all packets in transport and tunnel mode on the enc0 interface, I use net.enc.out.ipsec_filter_mask=1 and net.enc.in.ipsec_filter_mask=3. Further my server has included the patches given in kern/146190 to ignore checksums and kern/169620 to avoid packet bypass on ngX. The following patches are all for netipsec/key.c: I use parameter "generate_policy on" in racoon.conf. This works for clients with NAT-T, but direct connected clients need the following patch (likewise in ipsec-tools/roadwarrior/client/phase1-up.sh): @@ -1927,19 +1930,27 @@ #if 1 if (newsp->req && newsp->req->saidx.src.sa.sa_family) { struct sockaddr *sa; + uint16_t *pport; sa = (struct sockaddr *)(src0 + 1); if (sa->sa_family != newsp->req->saidx.src.sa.sa_family) { _key_delsp(newsp); return key_senderror(so, m, EINVAL); } + pport = (uint16_t *)newsp->req->saidx.src.sa.sa_data; + if ( *pport == htons(500) ) /* UDP_ENCAP_ESPINUDP_PORT */ + *pport = 0; } if (newsp->req && newsp->req->saidx.dst.sa.sa_family) { struct sockaddr *sa; + uint16_t *pport; sa = (struct sockaddr *)(dst0 + 1); if (sa->sa_family != newsp->req->saidx.dst.sa.sa_family) { _key_delsp(newsp); return key_senderror(so, m, EINVAL); } + pport = (uint16_t *)newsp->req->saidx.dst.sa.sa_data; + if ( *pport == htons(500) ) /* UDP_ENCAP_ESPINUDP_PORT */ + *pport = 0; } #endif The next patch eliminates a (probably not important) mistake in loop handling and an important change in calling key_cmpsaidx() from key_getsah(). With this patch mixed transport and tunnel modes behind the same router work correct. @@ -1312,11 +1312,14 @@ continue; if (key_cmpspidx_exactly(spidx, &sp->spidx)) { SP_ADDREF(sp); - break; + SPTREE_UNLOCK(); + goto found; } } SPTREE_UNLOCK(); + return NULL; + found: return sp; } @@ -2968,11 +2983,15 @@ LIST_FOREACH(sah, &V_sahtree, chain) { if (sah->state == SADB_SASTATE_DEAD) continue; - if (key_cmpsaidx(&sah->saidx, saidx, CMP_REQID)) - break; + if (key_cmpsaidx(&sah->saidx, saidx, CMP_MODE_REQID)) { + SAHTREE_UNLOCK(); + goto found; + } } SAHTREE_UNLOCK(); + return NULL; + found: return sah; } The last patch makes it possible for a transport mode client to open a new connection to the server immediately after closing an old connection. Without this patch the client must wait for the routers to forget all there NAT entries. @@ -4065,10 +4084,12 @@ /* * If NAT-T is enabled, check ports for tunnel mode. * Do not check ports if they are set to zero in the SPD. - * Also do not do it for transport mode, as there is no + * Also do not do it for native transport mode, as there is no * port information available in the SP. */ - if (saidx1->mode == IPSEC_MODE_TUNNEL && + if ((saidx1->mode == IPSEC_MODE_TUNNEL || + (saidx1->mode == IPSEC_MODE_TRANSPORT && + saidx1->proto == IPPROTO_ESP)) && saidx1->src.sa.sa_family == AF_INET && saidx1->dst.sa.sa_family == AF_INET && ((const struct sockaddr_in *)(&saidx1->src))->sin_port && One case is left: At the moment it is not possible for the kernel to handle more than one IPSEC/L2TP (transport mode) connection from clients behind the same NAT router. To get rid of this limitation the kernel must do some housekeeping for the clients inner and outer udp src ports (the corresponding dst ports are 1701 and 4500) to find the correct SA for outgoing packets. I do not know what would be the best place to store these informations. Any suggestions ? At the end a question: At the beginning of ip_ipsec_output() in ip_ipsec.c the flag PACKET_TAG_IPSEC_PENDING_TDB is used, but I can not find the place where this flag is set in the kernel. Can somebody enlighten me ? -- Dr. Andreas Longwitz Data Service GmbH Beethovenstr. 2A 23617 Stockelsdorf Amtsgericht Lübeck, HRB 318 BS Geschäftsführer: Wilfried Paepcke, Dr. Andreas Longwitz, Josef Flatau