From d52b1ace0346c0c7572ed17322fd740cfba822b3 Mon Sep 17 00:00:00 2001 From: patrick Date: Thu, 13 Apr 2017 07:04:09 +0000 Subject: [PATCH] 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@ --- sbin/iked/config.c | 3 ++- sbin/iked/iked.h | 6 +++++- sbin/iked/ikev2.c | 37 ++++++++++++++++++++++++++++++++++++- sbin/iked/ikev2_pld.c | 5 ++++- 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 @@ -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 @@ -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 @@ -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 @@ -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; -- 2.20.1