Attention is currently required from: plaisthos.
Hello plaisthos,
I'd like you to do a code review.
Please visit
http://gerrit.openvpn.net/c/openvpn/+/1771?usp=email
to review the following change.
Change subject: oob: fall back quickly when a handshake shortcut is ignored
......................................................................
oob: fall back quickly when a handshake shortcut is ignored
If the server does not accept the shortcut third packet (e.g. a middlebox
drops the larger P_CONTROL_WKC_V1, or a version/bug mismatch), the client
previously stalled for the full handshake_window (~60s) before recovering.
Give the shortcut session a short first-response deadline
(min(handshake_window, 5s)); once the server answers, tls_pre_decrypt()
restores the full window so a slow-but-working handshake is not cut off. If no
response arrives, the session times out quickly and the normal handshake
recovery kicks in, so a rejected shortcut costs a few seconds instead of ~60.
Change-Id: Icec4696ff263ab39ebab06e8d478395a5ddfaab9
Signed-off-by: Lev Stipakov <[email protected]>
---
M src/openvpn/ssl.c
M src/openvpn/ssl_common.h
2 files changed, 31 insertions(+), 1 deletion(-)
git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/71/1771/1
diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
index 4503a05..66f7af4 100644
--- a/src/openvpn/ssl.c
+++ b/src/openvpn/ssl.c
@@ -2516,6 +2516,11 @@
return session_move_pre_start(session, ks, true);
}
+/* Seconds to wait for the server's first response to an OOB handshake shortcut
+ * before giving up and falling back to a normal handshake. A couple of
+ * control-channel retransmits; capped at handshake_window by the caller. */
+#define OOB_SHORTCUT_FALLBACK_SECS 5
+
bool
session_skip_to_pre_start_client(struct tls_session *session, const struct
session_id *client_sid,
const struct session_id *server_sid,
@@ -2566,6 +2571,14 @@
return false;
}
ks->state = S_PRE_START;
+
+ /* Fail fast if the server ignores the shortcut: shorten the negotiation
+ * window to a few seconds (a couple of control-channel retransmits). If
the
+ * server answers, tls_pre_decrypt() restores the full window; if not, the
+ * session times out quickly and reset_session() retries with a normal
+ * handshake, rather than stalling for the whole handshake_window. */
+ ks->oob_shortcut = true;
+ ks->must_negotiate = now + min_int(session->opt->handshake_window,
OOB_SHORTCUT_FALLBACK_SECS);
return true;
}
@@ -2807,9 +2820,14 @@
/* Are we timed out on receive? */
if (now >= ks->must_negotiate && ks->state >= S_UNDEF && ks->state <
S_ACTIVE)
{
+ /* Report the window that actually applied: an unanswered OOB handshake
+ * shortcut times out on the short fallback deadline, not
handshake_window. */
+ int window = ks->oob_shortcut
+ ? min_int(session->opt->handshake_window,
OOB_SHORTCUT_FALLBACK_SECS)
+ : session->opt->handshake_window;
msg(D_TLS_ERRORS,
"TLS Error: TLS key negotiation failed to occur within %d seconds
(check your network connectivity)",
- session->opt->handshake_window);
+ window);
goto error;
}
@@ -3879,6 +3897,15 @@
/* Let our caller know we processed a control channel packet */
ret = true;
+ /* First valid response to an OOB handshake shortcut: the server accepted
it,
+ * so restore the normal negotiation window (it was shortened to fail fast
if
+ * the shortcut had been ignored). */
+ if (ks->oob_shortcut)
+ {
+ ks->oob_shortcut = false;
+ ks->must_negotiate = now + session->opt->handshake_window;
+ }
+
/*
* Set our remote address and remote session_id
*/
diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h
index 6f310a5..44f9dc0 100644
--- a/src/openvpn/ssl_common.h
+++ b/src/openvpn/ssl_common.h
@@ -227,6 +227,9 @@
time_t initial; /* when we created this session */
time_t established; /* when our state went S_ACTIVE */
time_t must_negotiate; /* key negotiation times out if not
finished before this time */
+ bool oob_shortcut; /* OOB handshake shortcut in
progress: must_negotiate is a
+ * short first-response deadline,
restored to the full window
+ * once the server answers (see
session_skip_to_pre_start_client) */
time_t must_die; /* this object is destroyed at this
time */
time_t peer_last_packet; /* Last time we received a packet
in this control session */
--
To view, visit http://gerrit.openvpn.net/c/openvpn/+/1771?usp=email
To unsubscribe, or for help writing mail filters, visit
http://gerrit.openvpn.net/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: openvpn
Gerrit-Branch: master
Gerrit-Change-Id: Icec4696ff263ab39ebab06e8d478395a5ddfaab9
Gerrit-Change-Number: 1771
Gerrit-PatchSet: 1
Gerrit-Owner: stipa <[email protected]>
Gerrit-Reviewer: plaisthos <[email protected]>
Gerrit-CC: openvpn-devel <[email protected]>
Gerrit-Attention: plaisthos <[email protected]>
_______________________________________________
Openvpn-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel