There seems to be an annoying bug in iked NAT traversal which leads to an iked
falsely seeing a NAT when the "local" IP is not explicitly set in the config,
as a result two ikeds will switch from port 500 to 4500 with the first
CREATE_CHILD_SA exchange.
The diff adds a new flag to the message and enables
udpencap based on whether the last message contained a NAT detection notify.

Ok?

Index: iked.h
===================================================================
RCS file: /mount/openbsd/cvs/src/sbin/iked/iked.h,v
retrieving revision 1.122
diff -u -p -u -r1.122 iked.h
--- iked.h      12 Aug 2019 07:40:45 -0000      1.122
+++ iked.h      13 Aug 2019 13:16:32 -0000
@@ -514,6 +514,7 @@ struct iked_message {
        int                      msg_valid;
        int                      msg_natt;
        int                      msg_natt_rcvd;
+       int                      msg_nat_detected;
        int                      msg_error;
        int                      msg_e;
        struct iked_message     *msg_parent;
Index: ikev2.c
===================================================================
RCS file: /mount/openbsd/cvs/src/sbin/iked/ikev2.c,v
retrieving revision 1.172
diff -u -p -u -r1.172 ikev2.c
--- ikev2.c     12 Aug 2019 07:40:45 -0000      1.172
+++ ikev2.c     13 Aug 2019 13:18:30 -0000
@@ -855,7 +855,7 @@ ikev2_init_recv(struct iked *env, struct
        if (!ikev2_msg_frompeer(msg))
                return;
 
-       if (sa->sa_udpencap && sa->sa_natt == 0 &&
+       if (sa && msg->msg_nat_detected && sa->sa_natt == 0 &&
            (sock = ikev2_msg_getsocket(env,
            sa->sa_local.addr_af, 1)) != NULL) {
                /*
@@ -872,9 +872,10 @@ ikev2_init_recv(struct iked *env, struct
                msg->msg_fd = sa->sa_fd = sock->sock_fd;
                msg->msg_sock = sock;
                sa->sa_natt = 1;
+               sa->sa_udpencap = 1;
 
-               log_debug("%s: NAT detected, updated SA to "
-                   "peer %s local %s", __func__,
+               log_debug("%s: detected NAT, enabling UDP encapsulation,"
+                   " updated SA to peer %s local %s", __func__,
                    print_host((struct sockaddr *)&sa->sa_peer.addr, NULL, 0),
                    print_host((struct sockaddr *)&sa->sa_local.addr, NULL, 0));
        }
@@ -2439,6 +2440,11 @@ ikev2_resp_ike_sa_init(struct iked *env,
        if (sa->sa_hdr.sh_initiator) {
                log_debug("%s: called by initiator", __func__);
                return (-1);
+       }
+       if (msg->msg_nat_detected && sa->sa_udpencap == 0) {
+               log_debug("%s: detected NAT, enabling UDP encapsulation",
+                   __func__);
+               sa->sa_udpencap = 1;
        }
 
        if ((buf = ikev2_msg_init(env, &resp,
Index: ikev2_pld.c
===================================================================
RCS file: /mount/openbsd/cvs/src/sbin/iked/ikev2_pld.c,v
retrieving revision 1.72
diff -u -p -u -r1.72 ikev2_pld.c
--- ikev2_pld.c 12 Aug 2019 07:40:45 -0000      1.72
+++ ikev2_pld.c 13 Aug 2019 13:16:32 -0000
@@ -1023,18 +1023,12 @@ ikev2_pld_notify(struct iked *env, struc
                if (ikev2_nat_detection(env, msg, md, sizeof(md), type) == -1)
                        return (-1);
                if (memcmp(buf, md, len) != 0) {
-                       log_debug("%s: %s detected NAT, enabling "
-                           "UDP encapsulation", __func__,
+                       log_debug("%s: %s detected NAT", __func__,
                            print_map(type, ikev2_n_map));
-
-                       /*
-                        * Enable UDP encapsulation of ESP packages if
-                        * the check detected NAT.
-                        */
-                       if (msg->msg_sa != NULL)
-                               msg->msg_sa->sa_udpencap = 1;
+                       msg->msg_parent->msg_nat_detected = 1;
                        /* Send keepalive, since we are behind a NAT-gw */
-                       if (type == IKEV2_N_NAT_DETECTION_DESTINATION_IP)
+                       if (msg->msg_sa != NULL &&
+                           type == IKEV2_N_NAT_DETECTION_DESTINATION_IP)
                                msg->msg_sa->sa_usekeepalive = 1;
                }
                print_hex(md, 0, sizeof(md));

Reply via email to