Date: Fri, 23 May 2014 15:27:50 +0200 From: Andreas Longwitz <longwitz@incore.de> To: freebsd-net@freebsd.org Subject: Support for IPSec VPN's with XAuth (tunnel mode) and L2TP (transport mode) Message-ID: <537F4CD6.8010305@incore.de>
next in thread | raw e-mail | index | archive | help
Hi, as continuation of http://lists.freebsd.org/pipermail/freebsd-net/2012-September/033170.html I like to give patches for two open problems: The first kernel patch of the link above is not needed anymore, vanhu pointed out: > It may be cleaner to have racoon generate the good SP entry, rather > than kernel trying to guess what is right in a SPDADD command. I agree , therefore I now use the following patch for racoon in the ipsec-tools-0.8.0_3 port: --- src/racoon/isakmp_quick.c.orig 2011-03-14 18:18:13.000000000 +0100 +++ src/racoon/isakmp_quick.c 2014-05-12 00:52:25.000000000 +0200 @@ -2012,6 +2012,13 @@ /* make inbound policy */ iph2->src = dst; iph2->dst = src; +#ifdef ENABLE_NATT + /* Without NAT the policies must include all ports. */ + if( !(iph2->ph1->natt_flags & NAT_DETECTED)) { + set_port(iph2->src, 0); + set_port(iph2->dst, 0); + } +#endif if (pk_sendspdupdate2(iph2) < 0) { plog(LLV_ERROR, LOCATION, NULL, "pfkey spdupdate2(inbound) failed.\n"); The other open task are IPSEC/L2TP (transport mode) connections from some clients behind the same NAT router. I do not longer try to solve this in the kernel and/or racoon, because it is a special "port 1701" problem. My propose is to handle this with the help of a connect-script introduced in mpd-5.6: --- src/l2tp.c.orig 2011-12-21 15:58:49.000000000 +0100 +++ src/l2tp.c 2014-05-14 11:39:24.000000000 +0200 @@ -67,6 +67,7 @@ struct u_range peer_addr; /* Peer IP addresses allowed */ in_port_t self_port; /* self port */ in_port_t peer_port; /* Peer port required (or zero) */ + char connect_script[IFACE_MAX_SCRIPT]; struct optinfo options; char callingnum[64]; /* L2TP phone number to use */ char callednum[64]; /* L2TP phone number to use */ @@ -90,6 +91,7 @@ enum { SET_SELFADDR, SET_PEERADDR, + SET_CONNECT_SCRIPT, SET_CALLINGNUM, SET_CALLEDNUM, SET_HOSTNAME, @@ -202,6 +204,8 @@ L2tpSetCommand, NULL, 2, (void *) SET_SELFADDR }, { "peer {ip} [{port}]", "Set remote IP address", L2tpSetCommand, NULL, 2, (void *) SET_PEERADDR }, + { "connect-script [{progname}]", "Set connect script", + L2tpSetCommand, NULL, 2, (void *) SET_CONNECT_SCRIPT }, { "callingnum {number}", "Set calling L2TP telephone number", L2tpSetCommand, NULL, 2, (void *) SET_CALLINGNUM }, { "callednum {number}", "Set called L2TP telephone number", @@ -913,6 +917,8 @@ Printf(", port %u", l2tp->conf.peer_port); Printf("\r\n"); Printf("\tHostname : %s\r\n", l2tp->conf.hostname); + Printf("\t connect-script: \"%s\"\r\n", + *l2tp->conf.connect_script ? l2tp->conf.connect_script : "<none>"); Printf("\tSecret : %s\r\n", (l2tp->conf.callingnum[0])?"******":""); Printf("\tCalling number: %s\r\n", l2tp->conf.callingnum); Printf("\tCalled number: %s\r\n", l2tp->conf.callednum); @@ -1438,6 +1444,22 @@ goto fail; } + /* Call "connect" script */ + if (*pi->conf.connect_script) { + char selfbuf[40],peerbuf[40]; + int res; + + res = ExecCmd(LG_IFACE2, "label", "%s %s %d %s %d", + pi->conf.connect_script, + u_addrtoa(&tun->self_addr, selfbuf, sizeof(selfbuf)),tun->self_port, + u_addrtoa(&tun->peer_addr, peerbuf, sizeof(peerbuf)), + tun->peer_port); + if (res != 0) { + Log(LG_PHYS, ("L2TP: Error running connect-script")); + goto fail; + } + } + /* Create vendor name AVP */ avps = ppp_l2tp_avp_list_create(); @@ -1747,6 +1769,18 @@ l2tp->conf.peer_port = port; } break; + case SET_CONNECT_SCRIPT: + switch (ac) { + case 0: + *l2tp->conf.connect_script = 0; + break; + case 1: + strlcpy(l2tp->conf.connect_script, av[0], sizeof(l2tp->conf.connect_script)); + break; + default: + return(-1); + } + break; case SET_CALLINGNUM: if (ac != 1) return(-1); Now in mpd.conf a connect-script can be defined which will be called for every new incoming L2TP packet: set l2tp connect-script /usr/local/etc/mpd5/l2tpConnect In /etc/ipsec.conf I only the policy for incoming packets is defined: spdadd 0.0.0.0/0[0] xx.xx.xx.xx[1701] udp -P in ipsec esp/transport//require; The policy for outgoing packets is created on the fly by the l2tpConnect script, I give an example thats working for me: set -- $* local_ip=$1 local_port=$2 # always 1701 remote_ip=$3 remote_port=$4 checkSAs() { status=0; while read line; do set -- ${line} param1="$1"; param2="$2"; param3="$3" case ${status} in 0) var1=${param1%[*}; var2=${param2%[*} if [ "${var1}" = "${local_ip}" -a "${var2}" = "${remote_ip}" ]; then dir=outbound; status=1 if [ "${param1}" = "${var1}" ]; then nat=0; port="500" else nat=1; var2=${param2%]}; port=${var2#*[} fi fi if [ "${var2}" = "${local_ip}" -a "${var1}" = "${remote_ip}" ]; then dir=inbound; status=1 fi ;; 1) if [ "${param2}" != "mode=transport" ]; then status=0 else var="${param3}"; var=${var%(*}; var=${var#*=} status=2 fi ;; 2) if [ "${param1}" = "allocated:" ]; then status=0 if [ "${param2}" = "0" -a "${dir}" = "outbound" ]; then SA_remote_port=${port}; SA_nat=${nat} fi fi ;; esac done echo "${SA_nat} ${SA_remote_port}" } SA=$(/usr/local/sbin/setkey -D | checkSAs) set -- ${SA} SA_nat=$1; SA_remote_port=$2 if [ ${SA_nat} = "1" ]; then src_dst="${local_ip}[4500]-${remote_ip}[${SA_remote_port}]" else src_dst="${local_ip}-${remote_ip}" fi echo "spdadd ${local_ip}[${local_port}] ${remote_ip}[${remote_port}] udp -P out ipsec esp/transport/${src_dst}/require;" | /usr/local/sbin/setkey -c -- Andreas Longwitz
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?537F4CD6.8010305>