iked(8): fix NAT traversal with empty "local" setting

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

iked(8): fix NAT traversal with empty "local" setting

Tobias Heider-2
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));