Support for IPSec VPN's with XAuth (tunnel mode) and L2TP (transport mode)
Andreas Longwitz
longwitz at incore.de
Fri May 23 13:35:03 UTC 2014
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
More information about the freebsd-net
mailing list