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));