tech-net archive

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


Le 19/05/2018 à 16:16, Chuck Zmudzinski a écrit :
What about RFC 3948 <>? 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'm not sure I understand. NetBSD _does_ support RFC3948. See udp4_espinudp()
in netinet/udp_usrreq.c.

What I was saying, is that we have code for draft-ietf-ipsec-udp-encaps-00,
that this code doesn't work, and that I don't think we are supposed to
support drafts.

I got my system to work by applying my patch shown in a previous message

I don't think the checksum part is necessary anymore. See
ipsec4_fixup_checksum() in ipsec_intput.c.

(This is not available on netbsd-7, though.)

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.

Indeed. So you fixed the problem I was talking about: if we substract 8 bytes
we hit the IP header, and not the UDP header.

However, it appears that you (or your application) got confused at some point.
This branch is taken when UDP_ENCAP_ESPINUDP_NON_IKE is set. This flag means
that we always want a "non-IKE marker", see [1].

The non-IKE marker is a 8-byte-sized zeroed area. So no, st[0] is not the SPI,
and st[1] is not the sequence number.

The fact that your application somehow reached this branch means that it did
set the UDP_ENCAP_ESPINUDP_NON_IKE flag. Therefore, for some reason, your
application is explicitly requesting non-IKE markers.

To me it looks like a misconfiguration. Your application requests non-IKE
markers, but it receives non-ESP markers. Given that in such a case st[1]!=0,
the kernel always thinks it needs to do normal UDP processing, while it should
do ESP processing. As a result nothing works.

What is your configuration? I bet that if you somehow change it to drop
non-IKE markers, it will work perfectly fine.


Home | Main Index | Thread Index | Old Index