tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: UDP_ENCAP_ESPINUDP_NON_IKE



What about RFC 3948 <https://tools.ietf.org/html/rfc3948>? I have an application that relies on this RFC, which is a NetBSD L2TP/IPSEC server for Windows clients behind NAT, and the NetBSD server also behind NAT. I was able to get this working to make a L2TP/IPSEC VPN connection from Windows clients to home networks such as the network behind AT&T U-verse or Comcast Xfinity resdential gateways.

The caveat is that I was not able to get this working with an unpatched NetBSD kernel because it appears code to support RFC 3948 is not enabled in NetBSD (at least not NetBSD 6 and 7).

FreeBSD removed this but they had code to support RFC 3948 that according to your reference 1 they suggested moving to netipsec/udpencap.c. There is no such code in NetBSD as far as I know.

I got my system to work by applying my patch shown in a previous message <http://mail-index.netbsd.org/tech-net/2017/09/22/msg006456.html>.

You are correct that the code in udp_usrreq.c does not work with Windows clients, which presumably uses RFC 3948 rather than draft-ietf-ipsec-udp-encaps-00. After some debugging I got this to work with Windows clients by patching that section of udp_usrreq.c (NetBSD 7.x) that is supposed to handle esp packets encapsulated in udp as follows:

--- netinet/udp_usrreq.c    2014-08-09 01:33:01.000000000 -0400
+++ netinet/udp_usrreq.c    2017-08-23 23:40:47.571414000 -0400
 @@ -1324,10 +1405,13 @@
         u_int32_t *st = (u_int32_t *)data;

         if ((len <= sizeof(u_int64_t) + sizeof(struct esp))
-            || ((st[0] | st[1]) != 0))
-            return 0; /* Normal UDP processing */
-
-        skip = sizeof(struct udphdr) + sizeof(u_int64_t);
+            || ((st[0] | st[1]) != 0)) {
+            /* From rfc 2406, 4303 for esp, st[0] is the spi */
+            /* From rfc 2406, 4303 for esp, st[1] is the sequence number */
+            if (!key_spiexists(st[0])) /* This is not an espinudp packet */
+                return 0; /* Normal UDP processing */
+        }
+        skip = sizeof(struct udphdr);
     }

     /*

Notice that my patch had to change the value of the skip variable to make my setup work. This patch is part of my much larger patch that I posted in an earlier thread on the tech-net mailing list <http://mail-index.netbsd.org/netbsd-users/2017/09/22/msg020168.html> where more details about my patch to make the VPN server work through NAT devices are given.

Chuck Zmudzinski

On 5/17/2018 2:16 AM, Maxime Villard wrote:
I think it would be good to retire UDP_ENCAP_ESPINUDP_NON_IKE. It is not
part of any RFC, it was just introduced in a draft, and then subsequently
removed from that draft.

RFC3948 makes authority, and it documents only the Non-ESP marker - that
is to say, UDP_ENCAP_ESPINUDP.

I think we are not supposed to support undocumented options.

FreeBSD did the same, see [1]. OpenBSD has never had that, it seems.

The reason I'm bringing this, is because there appears to be a bug with
UDP_ENCAP_ESPINUDP_NON_IKE, in udp_usrreq.c:

1317         skip = sizeof(struct udphdr) + 2 * sizeof(uint32_t);
1318     }
1319
1320     /*
1321      * Get the UDP ports. They are handled in network order
1322      * everywhere in the IPSEC_NAT_T code.
1323      */
1324     udphdr = (struct udphdr *)((char *)data - skip);

Here we have:

    data = mtod(m) + IP_header_len + sizeof(struct udphdr)

So it is wrong to substract 'skip', because then 'udphdr' will point to
some data in the IP header. I'm not sure if it means the code has never
worked, or if I'm just completely misreading it.

What do you think? I asked Ryota and Kengo, they don't know. One concern is raccoon, because it supports each draft that led to the RFC [2]. To me this is wrong too, there shouldn't be support for temporary specs, that have no
meaning once the RFC is out.

Don't know.

Maxime

[1] http://freshbsd.org/commit/freebsd/r309808
[2] https://nxr.netbsd.org/xref/src/crypto/dist/ipsec-tools/src/racoon/vendorid.c#67




Home | Main Index | Thread Index | Old Index