From owner-freebsd-stable@FreeBSD.ORG Wed May 2 18:50:12 2012 Return-Path: Delivered-To: freebsd-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 54256106564A for ; Wed, 2 May 2012 18:50:12 +0000 (UTC) (envelope-from zmiterby@gmail.com) Received: from mail-wi0-f172.google.com (mail-wi0-f172.google.com [209.85.212.172]) by mx1.freebsd.org (Postfix) with ESMTP id C53BA8FC18 for ; Wed, 2 May 2012 18:50:11 +0000 (UTC) Received: by wibhj6 with SMTP id hj6so4064382wib.13 for ; Wed, 02 May 2012 11:50:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=message-id:date:from:user-agent:mime-version:to:cc:subject :references:in-reply-to:content-type; bh=menhWYOj1Gld7XKc0UbH/+iSEuSDCfzo2ca0LKuoAKI=; b=kAAz1Z9xGkm4CKmMK8kynoUpsGixyhus5IWEySZue2Ml2sZZTCZXjX6hJmGQZZzQ/2 bq14B17x9KofGHP+fVRnp0TaD4Y8jbcqqYZhVqvR62QyBgGkjdXomDWLO1jp76zJ9jvS /5vBOXn6yapN6omtYcVF32bGUL3e9DVOL94jDQ1MrwFbkQsrH9RMXWZ209JGQWd/9Cjr AfwzzyMGf2y0C3LeOUVY7eSwZv5NWcMJGmjYEvFqJb7SjcNyYSKN65uw+n6emu0LGm0x sgtXULsXyYGQPy7MmspQKEq6GdE3UPJzi2fAVugBbw+Wl0odGxFJs9q9tyDslEQRIumm 3o2Q== Received: by 10.216.143.146 with SMTP id l18mr1502401wej.56.1335984610713; Wed, 02 May 2012 11:50:10 -0700 (PDT) Received: from [192.168.100.50] ([178.121.52.113]) by mx.google.com with ESMTPS id o2sm9278477wiv.11.2012.05.02.11.50.08 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 02 May 2012 11:50:09 -0700 (PDT) Message-ID: <4FA181E3.9020303@gmail.com> Date: Wed, 02 May 2012 21:50:11 +0300 From: Zmiter User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.2.13) Gecko/20101207 Thunderbird/3.1.7 MIME-Version: 1.0 To: Andreas Longwitz References: <4F970899.2040105@incore.de> In-Reply-To: <4F970899.2040105@incore.de> Content-Type: text/plain; charset=ISO-8859-15; format=flowed Content-Transfer-Encoding: 7bit X-Content-Filtered-By: Mailman/MimeDel 2.1.5 Cc: freebsd-stable@freebsd.org Subject: Re: Support for IPSec NAT-T in transoprt mode X-BeenThere: freebsd-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Production branch of FreeBSD source code List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 02 May 2012 18:50:12 -0000 24.04.2012 23:10, Andreas Longwitz ?????: > There is one limitation I would like to get over. From man 8 setkey: > System that do not perform the port check cannot support multiple > endpoints behind the same NAT. I think this is a FreeBSD kernel restriction: > For the first incoming L2TP packet the IPSEC part of the kernel does not > save the source port in the corresponding SA (maybe a field like > natt_l2tp_port). So the kernel does for outgoing L2TP packets not know > the correct SA, if two ore more SA's with the same IP exists. > > I would like to know if the patch mentioned in this thread adresses this > problem. Thank you very much for your attention. I've been testing those patches (actually, without your part) and YES it's a big problem with clients (Android, Windows Mobile) behind the same NAT. I cannot find the solution yet, but I'm very interested in it. So, my Androids is some sort of stupid bricks, they do not send NAT-OA payloads at phase 2, and ipsec-tools fills the SPD with IPs taken from IDs. But this is not the correct way. IDs contain LAN (which is behind the NAT) addresses, and FreeBSD cannot route packets to the IPSec crypto part. I've made some quick patching of IPSec tools to get my devices working, but I don't know if they accomodate to the RFCs and ISAKMP. The main idea is to take NAT-OAi and NAT-OAr addresses not from IDs when we are using NAT-T, but from real source and destination addresses of the server and client NATs. Here is my ipsec-tools patch (i've call it patch-zz-local-2.diff and place at /usr/ports/security/ipsec-tools/files with two other patches from kern /146190) *** src/racoon/pfkey.c 2012-04-13 02:02:02.000000000 +0300 --- src/racoon/pfkey.c 2012-04-19 12:47:57.000000000 +0300 *************** *** 1195,1200 **** --- 1195,1202 ---- #ifdef SADB_X_EXT_NAT_T_FRAG sa_args.l_natt_frag = iph2->ph1->rmconf->esp_frag; #endif + plog(LLV_DEBUG2, LOCATION, NULL, "sa_args.l_natt_oa = %s\n", saddr2str(sa_args.l_natt_oa)); + plog(LLV_DEBUG2, LOCATION, NULL, "sa_args.l_natt_oa_dst = %s\n", saddr2str(sa_args.l_natt_oa_dst)); } #endif *************** *** 1483,1488 **** --- 1485,1492 ---- #ifdef SADB_X_EXT_NAT_T_FRAG sa_args.l_natt_frag = iph2->ph1->rmconf->esp_frag; #endif + plog(LLV_DEBUG2, LOCATION, NULL, "sa_args.l_natt_oa = %s\n", saddr2str(sa_args.l_natt_oa)); + plog(LLV_DEBUG2, LOCATION, NULL, "sa_args.l_natt_oa_dst = %s\n", saddr2str(sa_args.l_natt_oa_dst)); } #endif /* more info to fill in */ *** src/racoon/isakmp_quick.c 2011-03-14 19:18:13.000000000 +0200 --- src/racoon/isakmp_quick.c 2012-04-19 17:23:16.000000000 +0300 *************** *** 562,567 **** --- 562,569 ---- if (daddr == NULL) goto end; + plog(LLV_DEBUG2, LOCATION, NULL, "daddr = %s, natoa_src = %s, natoa_dst = %s\n", saddr2str(daddr), saddr2str(iph2->natoa_src), saddr2str(iph2->natoa_dst)); + if (iph2->natoa_src == NULL) iph2->natoa_src = daddr; else if (iph2->natoa_dst == NULL) *************** *** 1262,1267 **** --- 1264,1271 ---- if (daddr == NULL) goto end; + plog(LLV_DEBUG2, LOCATION, NULL, "daddr = %s, natoa_src = %s, natoa_dst = %s\n", saddr2str(daddr), saddr2str(iph2->natoa_src), saddr2str(iph2->natoa_dst)); + if (iph2->natoa_dst == NULL) iph2->natoa_dst = daddr; else if (iph2->natoa_src == NULL) *************** *** 1309,1314 **** --- 1313,1345 ---- plogdump(LLV_DEBUG, iph2->id->v, iph2->id->l); } + #ifdef ENABLE_NATT + if (iph2->ph1->natt_flags& NAT_DETECTED) + { + struct sockaddr_storage addr; + u_int8_t prefix; + u_int16_t ul_proto; + + if (iph2->natoa_src == NULL) + if (!ipsecdoi_id2sockaddr(iph2->id, + (struct sockaddr *)&addr, + &prefix,&ul_proto)) + { + iph2->natoa_src = dupsaddr((struct sockaddr *)&addr); + plog(LLV_DEBUG2, LOCATION, NULL, "natoa_src set from IDcr2: natoa_src = %s\n", saddr2str(iph2->natoa_src)); + } + + if (iph2->natoa_dst == NULL) + if (!ipsecdoi_id2sockaddr(iph2->id_p, + (struct sockaddr *)&addr, + &prefix,&ul_proto)) + { + iph2->natoa_dst = dupsaddr((struct sockaddr *)&addr); + plog(LLV_DEBUG2, LOCATION, NULL, "natoa_dst set from IDci2: natoa_dst = %s\n", saddr2str(iph2->natoa_dst)); + } + } + #endif + /* adjust buffer length for HASH */ hbuf->l = tlen; *************** *** 2297,2302 **** --- 2328,2340 ---- } #endif + #ifdef ENABLE_NATT + if (iph2->ph1->natt_flags& NAT_DETECTED) + { + memcpy(&((struct sockaddr_in *)&spidx.dst)->sin_addr,&((struct sockaddr_in *)iph2->src)->sin_addr, sizeof(in_addr_t)); + } + #endif + if (_XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR) idi2type = _XIDT(iph2->id); *************** *** 2356,2361 **** --- 2394,2405 ---- } #endif + #ifdef ENABLE_NATT + if (iph2->ph1->natt_flags& NAT_DETECTED) + { + memcpy(&((struct sockaddr_in *)&spidx.src)->sin_addr,&((struct sockaddr_in *)iph2->dst)->sin_addr, sizeof(in_addr_t)); + } + #endif /* Before setting iph2->[sa_src, sa_dst] with the addresses * provided in ID payloads, we check: * - they are both addresses of same family ************************ end of patch ************************ And here is my sys/netipsec/ipsec_input.c patch: *** sys/netipsec/ipsec_input.c 2011-10-17 15:29:28.000000000 +0300 --- sys/netipsec/ipsec_input.c 2012-04-13 14:42:00.000000000 +0300 *************** *** 76,81 **** --- 76,86 ---- #include #endif + #ifdef IPSEC_NAT_T + #include + #include + #endif + #include #ifdef INET6 #include *************** *** 347,352 **** --- 352,383 ---- } prot = ip->ip_p; + #ifdef IPSEC_NAT_T + if (saidx->mode == IPSEC_MODE_TRANSPORT&& sproto == IPPROTO_ESP) { + if (V_esp_ignore_natt_cksum != 0) { + /* Ignore checksum of packet protected by ESP. */ + if (prot == IPPROTO_TCP || prot == IPPROTO_UDP) { + m->m_pkthdr.csum_flags |= (CSUM_DATA_VALID | CSUM_PSEUDO_HDR); + m->m_pkthdr.csum_data = 0xffff; + } + } else if (sav->natt_cksum != 0) { + if (prot == IPPROTO_TCP || prot == IPPROTO_UDP) { + u_int16_t proto_cksum; + int off = sizeof(struct ip); + if (prot == IPPROTO_TCP) { + off += offsetof(struct tcphdr, th_sum); + } else if (prot == IPPROTO_UDP) { + off += offsetof(struct udphdr, uh_sum); + } + m_copydata(m, off, sizeof(u_int16_t), (caddr_t)&proto_cksum); + proto_cksum = in_addword(sav->natt_cksum, ~ntohs(proto_cksum)); + proto_cksum = ~htons(proto_cksum); + m_copyback(m, off, sizeof(u_int16_t), (caddr_t)&proto_cksum); + } + } + } + #endif + #ifdef notyet /* IP-in-IP encapsulation */ if (prot == IPPROTO_IPIP) { ***************************** end of patch ***************************** It differs from that in kern/146190 in one simple thing. I have problems with the original patch from kern/146190. When there was no NAT-OAi or NAT-OAr values in the kernel space, checksums was calculated at 0, but they were not ignored despite of the sysctl net.inet.esp.esp_ignore_natt_cksum value. The improvement allows to ignore every checksum in esp packets when net.inet.esp.esp_ignore_natt_cksum=1. Thanks. Zmiter 02.05.2012