Hi Steffan,

Thanks for taking the time to improve this!

Regards,
Simon

> From: Simon Matter <simon.mat...@invoca.ch>
>
> While we were suffering from the "TLS Renegotiation Slowdown" bug here
> https://community.openvpn.net/openvpn/ticket/854 we realized that there is
> still room for improvement in our use case.
>
> It appears that TLS renegotiation is getting more and more expensive in
> terms of CPU cycles with recent changes for more security. To make things
> worse, we realized that most renegotiation procedures took place at almost
> the same time and increased the CPU load too much during these periods.
> That's especially true on large, multi-instance openvpn setups.
>
> I've created attached patch to add a per session pseudo-random component
> to
> the --reneg-sec intervals so that renegotiation is evenly spread over
> time.
> It is configured by simply adding a second value to --reneg-sec as
> described in the --help text:
>
> --reneg-sec max [min] : Renegotiate data chan. key after at most max
>                   (default=3600) and at least min (default 90% of max on
>                   servers and equal to max on clients).
>
> The jitter is only enabled by default on servers, because the actual reneg
> time is min(reneg_server, reneg_client).  Introducing jitter at both ends
> would bias the actual reneg time to the min value.
>
> Note that the patch also slightly changes the log output to show the sec
> value in the same way as the bytes/pkts values:
>
> TLS: soft reset sec=3084/3084 bytes=279897/-1 pkts=1370/0
>
> The idea and first versions of this patch are from Simon Matter.  Steffan
> Karger later incorporated the mailing list comments into this patch.  So
> credits go to Simon, and all bugs are Steffan's fault ;-)
>
> Signed-off-by: Simon Matter <simon.mat...@invoca.ch>
> Signed-off-by: Steffan Karger <stef...@karger.me>
> ---
> v3: incorporate comments from openvpn-devel@, don't add jitter by
>     default on the client side.
>
>  doc/openvpn.8         | 26 +++++++++++++++++++++-----
>  src/openvpn/init.c    | 15 ++++++++++++++-
>  src/openvpn/options.c | 11 +++++++++--
>  src/openvpn/options.h |  1 +
>  src/openvpn/ssl.c     |  6 +++---
>  5 files changed, 48 insertions(+), 11 deletions(-)
>
> diff --git a/doc/openvpn.8 b/doc/openvpn.8
> index a4189ac2..eb5258f9 100644
> --- a/doc/openvpn.8
> +++ b/doc/openvpn.8
> @@ -33,7 +33,7 @@
>  .\" .ft -- normal face
>  .\" .in +|-{n} -- indent
>  .\"
> -.TH openvpn 8 "25 August 2016"
> +.TH openvpn 8 "04 April 2017"
>  .\"*********************************************************
>  .SH NAME
>  openvpn \- secure IP tunnel daemon.
> @@ -4957,10 +4957,26 @@ Renegotiate data channel key after
>  packets sent and received (disabled by default).
>  .\"*********************************************************
>  .TP
> -.B \-\-reneg\-sec n
> -Renegotiate data channel key after
> -.B n
> -seconds (default=3600).
> +.B \-\-reneg\-sec max [min]
> +Renegotiate data channel key after at most
> +.B max
> +seconds (default=3600) and at least
> +.B min
> +seconds (default is 90% of
> +.B max
> +for servers, and equal to
> +.B max
> +for clients).
> +
> +The effective
> +.B reneg\-sec
> +value used is per session pseudo-uniform-randomized between
> +.B min
> +and
> +.B max\fR.
> +
> +With the default value of 3600 this results in an effective per session
> value
> +in the range of 3240..3600 seconds for servers, or just 3600 for clients.
>
>  When using dual\-factor authentication, note that this default value may
>  cause the end user to be challenged to reauthorize once per hour.
> diff --git a/src/openvpn/init.c b/src/openvpn/init.c
> index 1ed2c55e..0b64930e 100644
> --- a/src/openvpn/init.c
> +++ b/src/openvpn/init.c
> @@ -2693,7 +2693,20 @@ do_init_crypto_tls(struct context *c, const
> unsigned int flags)
>      to.packet_timeout = options->tls_timeout;
>      to.renegotiate_bytes = options->renegotiate_bytes;
>      to.renegotiate_packets = options->renegotiate_packets;
> -    to.renegotiate_seconds = options->renegotiate_seconds;
> +    if (options->renegotiate_seconds_min < 0)
> +    {
> +        /* Add 10% jitter to the reneg-sec of each connection by default
> */
> +        int auto_jitter = options->mode != MODE_SERVER ? 0 :
> +                get_random() % max_int(options->renegotiate_seconds / 10,
> 1);
> +        to.renegotiate_seconds = options->renegotiate_seconds -
> auto_jitter;
> +    }
> +    else
> +    {
> +        /* Add user-specific jitter to the renge-sec of each connection
> */
> +        to.renegotiate_seconds = options->renegotiate_seconds -
> +                (get_random() % max_int(options->renegotiate_seconds
> +                                        -
> options->renegotiate_seconds_min, 1));
> +    }
>      to.single_session = options->single_session;
>      to.mode = options->mode;
>      to.pull = options->pull;
> diff --git a/src/openvpn/options.c b/src/openvpn/options.c
> index 641a26e2..7fe22064 100644
> --- a/src/openvpn/options.c
> +++ b/src/openvpn/options.c
> @@ -603,7 +603,9 @@ static const char usage_message[] =
>      "                  if no ACK from remote within n seconds
> (default=%d).\n"
>      "--reneg-bytes n : Renegotiate data chan. key after n bytes sent and
> recvd.\n"
>      "--reneg-pkts n  : Renegotiate data chan. key after n packets sent
> and recvd.\n"
> -    "--reneg-sec n   : Renegotiate data chan. key after n seconds
> (default=%d).\n"
> +    "--reneg-sec max [min] : Renegotiate data chan. key after at most max
> (default=%d)\n"
> +    "                  and at least min (defaults to 90%% of max on
> servers and equal\n"
> +    "                  to max on clients).\n"
>      "--hand-window n : Data channel key exchange must finalize within n
> seconds\n"
>      "                  of handshake initiation by any peer
> (default=%d).\n"
>      "--tran-window n : Transition window -- old key can live this many
> seconds\n"
> @@ -870,6 +872,7 @@ init_options(struct options *o, const bool init_gc)
>      o->tls_timeout = 2;
>      o->renegotiate_bytes = -1;
>      o->renegotiate_seconds = 3600;
> +    o->renegotiate_seconds_min = -1;
>      o->handshake_window = 60;
>      o->transition_window = 3600;
>      o->ecdh_curve = NULL;
> @@ -7999,10 +8002,14 @@ add_option(struct options *options,
>          VERIFY_PERMISSION(OPT_P_TLS_PARMS);
>          options->renegotiate_packets = positive_atoi(p[1]);
>      }
> -    else if (streq(p[0], "reneg-sec") && p[1] && !p[2])
> +    else if (streq(p[0], "reneg-sec") && p[1] && !p[3])
>      {
>          VERIFY_PERMISSION(OPT_P_TLS_PARMS);
>          options->renegotiate_seconds = positive_atoi(p[1]);
> +        if (p[2])
> +        {
> +            options->renegotiate_seconds_min = positive_atoi(p[2]);
> +        }
>      }
>      else if (streq(p[0], "hand-window") && p[1] && !p[2])
>      {
> diff --git a/src/openvpn/options.h b/src/openvpn/options.h
> index 496c1143..a74dc94d 100644
> --- a/src/openvpn/options.h
> +++ b/src/openvpn/options.h
> @@ -548,6 +548,7 @@ struct options
>      int renegotiate_bytes;
>      int renegotiate_packets;
>      int renegotiate_seconds;
> +    int renegotiate_seconds_min;
>
>      /* Data channel key handshake must finalize
>       * within n seconds of handshake initiation. */
> diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
> index cb94229a..174f13cb 100644
> --- a/src/openvpn/ssl.c
> +++ b/src/openvpn/ssl.c
> @@ -2732,9 +2732,9 @@ tls_process(struct tls_multi *multi,
>                  && ks->n_packets >= session->opt->renegotiate_packets)
>              ||
> (packet_id_close_to_wrapping(&ks->crypto_options.packet_id.send))))
>      {
> -        msg(D_TLS_DEBUG_LOW,
> -            "TLS: soft reset sec=%d bytes=" counter_format "/%d pkts="
> counter_format "/%d",
> -            (int)(ks->established + session->opt->renegotiate_seconds -
> now),
> +        msg(D_TLS_DEBUG_LOW, "TLS: soft reset sec=%lld/%d bytes="
> counter_format
> +            "/%d pkts=" counter_format "/%d",
> +            (now - ks->established), session->opt->renegotiate_seconds,
>              ks->n_bytes, session->opt->renegotiate_bytes,
>              ks->n_packets, session->opt->renegotiate_packets);
>          key_state_soft_reset(session);
> --
> 2.14.1
>



------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to