Hi Steffan,

While running your v3 version of the patch I found an issue with the
modified logging. It gives the following error while building

gcc -DHAVE_CONFIG_H -I. -I../.. -I../../include  -I../../include
-I../../src/compat       -DPLUGIN_LIBDIR=\"/usr/lib64/openvpn/plugins\" 
-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions
-fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches  
-m64 -mtune=generic -std=c99 -c -o ssl.o ssl.c
ssl.c: In function 'tls_process':
ssl.c:2735:9: warning: format '%lld' expects argument of type 'long long
int', but argument 3 has type 'time_t' [-Wformat=]
         msg(D_TLS_DEBUG_LOW, "TLS: soft reset sec=%lld/%d bytes="
counter_format
         ^
and the log output is also corrupted

TLS: soft reset sec=14774687501680/336605974
bytes=18446744069414584320/581335 pkts=0/0
TLS: soft reset sec=14787572403571/77375 bytes=18446744069414584320/885
pkts=0/-1080308296
TLS: soft reset sec=14164802145506/6746662
bytes=18446744069414584320/86778 pkts=0/0
TLS: soft reset sec=15264313773538/186529 bytes=18446744069414584320/1108
pkts=0/13935244

Please have a look at the attached v4 patch which fixes it for me. The
output is now

TLS: soft reset sec=3474/3474 bytes=8470454/-1 pkts=108673/0
TLS: soft reset sec=3489/3489 bytes=429623769/-1 pkts=656033/0
TLS: soft reset sec=3517/3517 bytes=89365/-1 pkts=877/0
TLS: soft reset sec=3537/3537 bytes=206142/-1 pkts=1123/0

which seems reasonable to me.
In the patch I've modified the lines below:

         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),
+            "TLS: soft reset sec=%d/%d bytes=" counter_format "/%d pkts="
counter_format "/%d",
+            (int)(now - ks->established), session->opt->renegotiate_seconds,
             ks->n_bytes, session->opt->renegotiate_bytes,

I'm not a developer and not a git user, so please accept my hand crafted
patch work :-)

Thanks and 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
>
diff -Naur openvpn-2.4.4.orig/doc/openvpn.8 openvpn-2.4.4/doc/openvpn.8
--- openvpn-2.4.4.orig/doc/openvpn.8	2017-09-26 11:27:37.000000000 +0200
+++ openvpn-2.4.4/doc/openvpn.8	2017-11-14 09:10:35.000000000 +0100
@@ -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.
@@ -4958,10 +4958,26 @@
 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 -Naur openvpn-2.4.4.orig/src/openvpn/init.c openvpn-2.4.4/src/openvpn/init.c
--- openvpn-2.4.4.orig/src/openvpn/init.c	2017-09-26 11:27:37.000000000 +0200
+++ openvpn-2.4.4/src/openvpn/init.c	2017-11-14 09:10:35.000000000 +0100
@@ -2706,7 +2706,20 @@
     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 server 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 reneg-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 -Naur openvpn-2.4.4.orig/src/openvpn/options.c openvpn-2.4.4/src/openvpn/options.c
--- openvpn-2.4.4.orig/src/openvpn/options.c	2017-09-26 11:27:37.000000000 +0200
+++ openvpn-2.4.4/src/openvpn/options.c	2017-11-14 09:10:35.000000000 +0100
@@ -604,7 +604,9 @@
     "                  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"
@@ -872,6 +874,7 @@
     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;
@@ -8018,10 +8021,14 @@
         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 -Naur openvpn-2.4.4.orig/src/openvpn/options.h openvpn-2.4.4/src/openvpn/options.h
--- openvpn-2.4.4.orig/src/openvpn/options.h	2017-09-26 11:27:37.000000000 +0200
+++ openvpn-2.4.4/src/openvpn/options.h	2017-11-14 09:10:35.000000000 +0100
@@ -549,6 +549,7 @@
     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 -Naur openvpn-2.4.4.orig/src/openvpn/ssl.c openvpn-2.4.4/src/openvpn/ssl.c
--- openvpn-2.4.4.orig/src/openvpn/ssl.c	2017-09-26 11:27:37.000000000 +0200
+++ openvpn-2.4.4/src/openvpn/ssl.c	2017-11-14 09:19:03.000000000 +0100
@@ -2733,8 +2733,8 @@
             || (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),
+            "TLS: soft reset sec=%d/%d bytes=" counter_format "/%d pkts=" counter_format "/%d",
+            (int)(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);
------------------------------------------------------------------------------
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