summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2017-04-13 07:04:10 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2017-04-13 07:04:10 +0000
commit6370a5ccd60fbe7c6a6a804f6f4ccc77dc2dde81 (patch)
treea68d93628ee47c4722dc2f0ee1bc586142d06810
parentf9008673f7067d35956794a87d8185a8c8628749 (diff)
Add a NAT-T keepalive timer in case we are behind a NAT gateway.
See RFC 5996, section 2.23, NAT Traversal: In the case of a mismatching NAT_DETECTION_DESTINATION_IP hash, it means that the system receiving the NAT_DETECTION_DESTINATION_IP payload is behind a NAT and that system SHOULD start sending keepalive packets as defined in [UDPENCAPS]. With markus@, ok reyk@
-rw-r--r--sbin/iked/config.c3
-rw-r--r--sbin/iked/iked.h6
-rw-r--r--sbin/iked/ikev2.c37
-rw-r--r--sbin/iked/ikev2_pld.c5
4 files changed, 47 insertions, 4 deletions
diff --git a/sbin/iked/config.c b/sbin/iked/config.c
index d24da1445c9..590e4d7f4da 100644
--- a/sbin/iked/config.c
+++ b/sbin/iked/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.47 2017/03/27 10:43:53 mikeb Exp $ */
+/* $OpenBSD: config.c,v 1.48 2017/04/13 07:04:09 patrick Exp $ */
/*
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
@@ -97,6 +97,7 @@ void
config_free_sa(struct iked *env, struct iked_sa *sa)
{
timer_del(env, &sa->sa_timer);
+ timer_del(env, &sa->sa_keepalive);
timer_del(env, &sa->sa_rekey);
config_free_proposals(&sa->sa_proposals, 0);
diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h
index 25e81ea34a8..7e77d206f77 100644
--- a/sbin/iked/iked.h
+++ b/sbin/iked/iked.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: iked.h,v 1.113 2017/03/27 17:17:49 mikeb Exp $ */
+/* $OpenBSD: iked.h,v 1.114 2017/04/13 07:04:09 patrick Exp $ */
/*
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
@@ -376,6 +376,7 @@ struct iked_sa {
int sa_natt; /* for IKE messages */
int sa_udpencap; /* for pfkey */
+ int sa_usekeepalive;/* NAT-T keepalive */
int sa_state;
unsigned int sa_stateflags;
@@ -446,6 +447,9 @@ struct iked_sa {
#define IKED_IKE_SA_DELETE_TIMEOUT 120 /* 2 minutes */
#define IKED_IKE_SA_ALIVE_TIMEOUT 60 /* 1 minute */
+ struct iked_timer sa_keepalive; /* keepalive timer */
+#define IKED_IKE_SA_KEEPALIVE_TIMEOUT 20
+
struct iked_timer sa_rekey; /* rekey timeout */
struct iked_msgqueue sa_requests; /* request queue */
diff --git a/sbin/iked/ikev2.c b/sbin/iked/ikev2.c
index cd8b0d89b95..078886ce604 100644
--- a/sbin/iked/ikev2.c
+++ b/sbin/iked/ikev2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ikev2.c,v 1.152 2017/03/30 15:48:30 patrick Exp $ */
+/* $OpenBSD: ikev2.c,v 1.153 2017/04/13 07:04:09 patrick Exp $ */
/*
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
@@ -89,6 +89,7 @@ void ikev2_ike_sa_rekey_timeout(struct iked *, void *);
void ikev2_ike_sa_rekey_schedule(struct iked *, struct iked_sa *);
void ikev2_ike_sa_timeout(struct iked *env, void *);
void ikev2_ike_sa_alive(struct iked *, void *);
+void ikev2_ike_sa_keepalive(struct iked *, void *);
int ikev2_sa_initiator(struct iked *, struct iked_sa *,
struct iked_sa *, struct iked_message *);
@@ -1200,6 +1201,10 @@ ikev2_init_done(struct iked *env, struct iked_sa *sa)
timer_del(env, &sa->sa_timer);
timer_set(env, &sa->sa_timer, ikev2_ike_sa_alive, sa);
timer_add(env, &sa->sa_timer, IKED_IKE_SA_ALIVE_TIMEOUT);
+ timer_set(env, &sa->sa_keepalive, ikev2_ike_sa_keepalive, sa);
+ if (sa->sa_usekeepalive)
+ timer_add(env, &sa->sa_keepalive,
+ IKED_IKE_SA_KEEPALIVE_TIMEOUT);
timer_set(env, &sa->sa_rekey, ikev2_ike_sa_rekey, sa);
if (sa->sa_policy->pol_rekey)
ikev2_ike_sa_rekey_schedule(env, sa);
@@ -2473,6 +2478,10 @@ ikev2_resp_ike_auth(struct iked *env, struct iked_sa *sa)
timer_del(env, &sa->sa_timer);
timer_set(env, &sa->sa_timer, ikev2_ike_sa_alive, sa);
timer_add(env, &sa->sa_timer, IKED_IKE_SA_ALIVE_TIMEOUT);
+ timer_set(env, &sa->sa_keepalive, ikev2_ike_sa_keepalive, sa);
+ if (sa->sa_usekeepalive)
+ timer_add(env, &sa->sa_keepalive,
+ IKED_IKE_SA_KEEPALIVE_TIMEOUT);
timer_set(env, &sa->sa_rekey, ikev2_ike_sa_rekey, sa);
if (sa->sa_policy->pol_rekey)
ikev2_ike_sa_rekey_schedule(env, sa);
@@ -3142,6 +3151,7 @@ ikev2_ikesa_enable(struct iked *env, struct iked_sa *sa, struct iked_sa *nsa)
nsa->sa_fd = sa->sa_fd;
nsa->sa_natt = sa->sa_natt;
nsa->sa_udpencap = sa->sa_udpencap;
+ nsa->sa_usekeepalive = sa->sa_usekeepalive;
/* Transfer old addresses */
memcpy(&nsa->sa_local, &sa->sa_local, sizeof(nsa->sa_local));
@@ -3226,6 +3236,10 @@ ikev2_ikesa_enable(struct iked *env, struct iked_sa *sa, struct iked_sa *nsa)
sa_state(env, nsa, IKEV2_STATE_ESTABLISHED);
timer_set(env, &nsa->sa_timer, ikev2_ike_sa_alive, nsa);
timer_add(env, &nsa->sa_timer, IKED_IKE_SA_ALIVE_TIMEOUT);
+ timer_set(env, &nsa->sa_keepalive, ikev2_ike_sa_keepalive, nsa);
+ if (nsa->sa_usekeepalive)
+ timer_add(env, &nsa->sa_keepalive,
+ IKED_IKE_SA_KEEPALIVE_TIMEOUT);
timer_set(env, &nsa->sa_rekey, ikev2_ike_sa_rekey, nsa);
if (nsa->sa_policy->pol_rekey)
ikev2_ike_sa_rekey_schedule(env, nsa);
@@ -3234,6 +3248,7 @@ ikev2_ikesa_enable(struct iked *env, struct iked_sa *sa, struct iked_sa *nsa)
/* unregister DPD keep alive timer & rekey first */
if (sa->sa_state == IKEV2_STATE_ESTABLISHED) {
timer_del(env, &sa->sa_rekey);
+ timer_del(env, &sa->sa_keepalive);
timer_del(env, &sa->sa_timer);
}
@@ -3626,6 +3641,26 @@ ikev2_ike_sa_alive(struct iked *env, void *arg)
timer_add(env, &sa->sa_timer, IKED_IKE_SA_ALIVE_TIMEOUT);
}
+void
+ikev2_ike_sa_keepalive(struct iked *env, void *arg)
+{
+ struct iked_sa *sa = arg;
+ uint8_t marker = 0xff;
+
+ if (sendtofrom(sa->sa_fd, &marker, sizeof(marker), 0,
+ (struct sockaddr *)&sa->sa_peer.addr, sa->sa_peer.addr.ss_len,
+ (struct sockaddr *)&sa->sa_local.addr, sa->sa_local.addr.ss_len)
+ == -1)
+ log_warn("%s: sendtofrom: 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));
+ else
+ log_debug("%s: 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));
+ timer_add(env, &sa->sa_keepalive, IKED_IKE_SA_KEEPALIVE_TIMEOUT);
+}
+
int
ikev2_send_informational(struct iked *env, struct iked_message *msg)
{
diff --git a/sbin/iked/ikev2_pld.c b/sbin/iked/ikev2_pld.c
index 86086e56ca4..5724520f696 100644
--- a/sbin/iked/ikev2_pld.c
+++ b/sbin/iked/ikev2_pld.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ikev2_pld.c,v 1.61 2017/03/27 17:17:49 mikeb Exp $ */
+/* $OpenBSD: ikev2_pld.c,v 1.62 2017/04/13 07:04:09 patrick Exp $ */
/*
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
@@ -1148,6 +1148,9 @@ ikev2_pld_notify(struct iked *env, struct ikev2_payload *pld,
*/
if (msg->msg_sa != NULL)
msg->msg_sa->sa_udpencap = 1;
+ /* Send keepalive, since we are behind a NAT-gw */
+ if (type == IKEV2_N_NAT_DETECTION_DESTINATION_IP)
+ msg->msg_sa->sa_usekeepalive = 1;
}
print_hex(md, 0, sizeof(md));
break;