summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRemi Tricot-Le Breton <rlebreton@haproxy.com>2023-02-28 17:46:29 +0100
committerWilliam Lallemand <wlallemand@haproxy.org>2023-03-02 15:37:23 +0100
commit5843237993d4f53e3ccfb4dbedf35e2219c634eb (patch)
treec7cf974594c6c506bc086db2bbc20935e5ba35e9
parent9c4437d0241a8d2e29b1693e0a8d7e1b2894e64e (diff)
downloadhaproxy-5843237993d4f53e3ccfb4dbedf35e2219c634eb.tar.gz
MINOR: ssl: Add global options to modify ocsp update min/max delay
The minimum and maximum delays between two automatic updates of a given OCSP response can now be set via global options. It allows to limit the update rate of OCSP responses for configurations that use many frontend certificates with the ocsp-update option set if the updates are deemed too costly.
-rw-r--r--doc/configuration.txt27
-rw-r--r--include/haproxy/ssl_ocsp-t.h5
-rw-r--r--include/haproxy/ssl_sock-t.h7
-rw-r--r--src/cfgparse-ssl.c57
-rw-r--r--src/ssl_ocsp.c10
-rw-r--r--src/ssl_sock.c6
6 files changed, 103 insertions, 9 deletions
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 4538af74e..ae9c49e31 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -1188,6 +1188,8 @@ The following keywords are supported in the "global" section :
- tune.ssl.lifetime
- tune.ssl.maxrecord
- tune.ssl.ssl-ctx-cache-size
+ - tune.ssl.ocsp-update.maxdelay
+ - tune.ssl.ocsp-update.mindelay
- tune.vars.global-max-size
- tune.vars.proc-max-size
- tune.vars.reqres-max-size
@@ -3355,6 +3357,25 @@ tune.ssl.ssl-ctx-cache-size <number>
dynamically is expensive, they are cached. The default cache size is set to
1000 entries.
+tune.ssl.ocsp-update.maxdelay <number>
+ Sets the maximum interval between two automatic updates of the same OCSP
+ response. This time is expressed in seconds and defaults to 3600 (1 hour). It
+ must be set to a higher value than "tune.ssl.ocsp-update.mindelay". See
+ option "ocsp-update" for more information about the auto update mechanism.
+
+tune.ssl.ocsp-update.mindelay <number>
+ Sets the minimum interval between two automatic updates of the same OCSP
+ response. This time is expressed in seconds and defaults to 300 (5 minutes).
+ It is particularly useful for OCSP response that do not have explicit
+ expiration times. It must be set to a lower value than
+ "tune.ssl.ocsp-update.maxdelay". See option "ocsp-update" for more
+ information about the auto update mechanism.
+
+ Sets the size of the cache used to store generated certificates to <number>
+ entries. This is a LRU cache. Because generating a SSL certificate
+ dynamically is expensive, they are cached. The default cache size is set to
+ 1000 entries.
+
tune.stick-counters <number>
Sets the number of stick-counters that may be tracked at the same time by a
connection or a request via "track-sc*" actions in "tcp-request" or
@@ -14946,7 +14967,11 @@ ocsp-update [ off | on ]
short time after init.
On the other hand, if a certificate has an OCSP uri specified and no OCSP
response, setting this option to 'on' for the given certificate will ensure
- that the OCSP response gets fetched automatically right after init.
+ that the OCSP response gets fetched automatically right after init. The
+ default minimum and maximum delays (5 minutes and 1 hour respectively) can be
+ configured by the "tune.ssl.ocsp-update.maxdelay" and
+ "tune.ssl.ocsp-update.mindelay" global options.
+
Whenever an OCSP response is updated by the auto update task, a dedicated log
line is emitted. It will follow a dedicated log-format that looks like the
following "%ci:%cp [%tr] %ft %[ssl_ocsp_certid] %[ssl_ocsp_status]
diff --git a/include/haproxy/ssl_ocsp-t.h b/include/haproxy/ssl_ocsp-t.h
index 44484319f..d78f94164 100644
--- a/include/haproxy/ssl_ocsp-t.h
+++ b/include/haproxy/ssl_ocsp-t.h
@@ -33,6 +33,11 @@
extern int ocsp_ex_index;
#endif
+#define SSL_OCSP_UPDATE_DELAY_MAX 60*60 /* 1H */
+#define SSL_OCSP_UPDATE_DELAY_MIN 5*60 /* 5 minutes */
+#define SSL_OCSP_UPDATE_MARGIN 60 /* 1 minute */
+#define SSL_OCSP_HTTP_ERR_REPLAY 60 /* 1 minute */
+
#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
/*
* struct alignment works here such that the key.key is the same as key_data
diff --git a/include/haproxy/ssl_sock-t.h b/include/haproxy/ssl_sock-t.h
index f7a96ba5c..661c70027 100644
--- a/include/haproxy/ssl_sock-t.h
+++ b/include/haproxy/ssl_sock-t.h
@@ -293,6 +293,13 @@ struct global_ssl {
int keylog; /* activate keylog */
int extra_files; /* which files not defined in the configuration file are we looking for */
int extra_files_noext; /* whether we remove the extension when looking up a extra file */
+
+#ifndef OPENSSL_NO_OCSP
+ struct {
+ unsigned int delay_max;
+ unsigned int delay_min;
+ } ocsp_update;
+#endif
};
/* The order here matters for picking a default context,
diff --git a/src/cfgparse-ssl.c b/src/cfgparse-ssl.c
index 655115f52..1b33eecb8 100644
--- a/src/cfgparse-ssl.c
+++ b/src/cfgparse-ssl.c
@@ -1906,6 +1906,59 @@ static int ssl_parse_skip_self_issued_ca(char **args, int section_type, struct p
}
+static int ssl_parse_global_ocsp_maxdelay(char **args, int section_type, struct proxy *curpx,
+ const struct proxy *defpx, const char *file, int line,
+ char **err)
+{
+ int value = 0;
+
+ if (*(args[1]) == 0) {
+ memprintf(err, "'%s' expects an integer argument.", args[0]);
+ return -1;
+ }
+
+ value = atoi(args[1]);
+ if (value < 0) {
+ memprintf(err, "'%s' expects a positive numeric value.", args[0]);
+ return -1;
+ }
+
+ if (global_ssl.ocsp_update.delay_min > value) {
+ memprintf(err, "'%s' can not be lower than tune.ssl.ocsp-update.mindelay.", args[0]);
+ return -1;
+ }
+
+ global_ssl.ocsp_update.delay_max = value;
+
+ return 0;
+}
+
+static int ssl_parse_global_ocsp_mindelay(char **args, int section_type, struct proxy *curpx,
+ const struct proxy *defpx, const char *file, int line,
+ char **err)
+{
+ int value = 0;
+
+ if (*(args[1]) == 0) {
+ memprintf(err, "'%s' expects an integer argument.", args[0]);
+ return -1;
+ }
+
+ value = atoi(args[1]);
+ if (value < 0) {
+ memprintf(err, "'%s' expects a positive numeric value.", args[0]);
+ return -1;
+ }
+
+ if (value > global_ssl.ocsp_update.delay_max) {
+ memprintf(err, "'%s' can not be higher than tune.ssl.ocsp-update.maxdelay.", args[0]);
+ return -1;
+ }
+
+ global_ssl.ocsp_update.delay_min = value;
+
+ return 0;
+}
@@ -2081,6 +2134,10 @@ static struct cfg_kw_list cfg_kws = {ILH, {
#endif
{ CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files },
{ CFG_GLOBAL, "ssl-load-extra-del-ext", ssl_parse_global_extra_noext },
+#ifndef OPENSSL_NO_OCSP
+ { CFG_GLOBAL, "tune.ssl.ocsp-update.maxdelay", ssl_parse_global_ocsp_maxdelay },
+ { CFG_GLOBAL, "tune.ssl.ocsp-update.mindelay", ssl_parse_global_ocsp_mindelay },
+#endif
{ 0, NULL, NULL },
}};
diff --git a/src/ssl_ocsp.c b/src/ssl_ocsp.c
index db736fab3..3cd35a530 100644
--- a/src/ssl_ocsp.c
+++ b/src/ssl_ocsp.c
@@ -183,10 +183,6 @@ struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
__decl_thread(HA_SPINLOCK_T ocsp_tree_lock);
struct eb_root ocsp_update_tree = EB_ROOT; /* updatable ocsp responses sorted by next_update in absolute time */
-#define SSL_OCSP_UPDATE_DELAY_MAX 60*60 /* 1H */
-#define SSL_OCSP_UPDATE_DELAY_MIN 5*60 /* 5 minutes */
-#define SSL_OCSP_UPDATE_MARGIN 60 /* 1 minute */
-#define SSL_OCSP_HTTP_ERR_REPLAY 60 /* 1 minute */
/* This function starts to check if the OCSP response (in DER format) contained
* in chunk 'ocsp_response' is valid (else exits on error).
@@ -916,7 +912,7 @@ static inline void ssl_ocsp_set_next_update(struct certificate_ocsp *ocsp)
{
int update_margin = (ocsp->expire >= SSL_OCSP_UPDATE_MARGIN) ? SSL_OCSP_UPDATE_MARGIN : 0;
- ocsp->next_update.key = MIN(now.tv_sec + SSL_OCSP_UPDATE_DELAY_MAX,
+ ocsp->next_update.key = MIN(now.tv_sec + global_ssl.ocsp_update.delay_max,
ocsp->expire - update_margin);
/* An already existing valid OCSP response that expires within less than
@@ -925,7 +921,7 @@ static inline void ssl_ocsp_set_next_update(struct certificate_ocsp *ocsp)
* update of the same response. */
if (b_data(&ocsp->response))
ocsp->next_update.key = MAX(ocsp->next_update.key,
- now.tv_sec + SSL_OCSP_UPDATE_DELAY_MIN);
+ now.tv_sec + global_ssl.ocsp_update.delay_min);
}
/*
@@ -980,7 +976,7 @@ int ssl_ocsp_update_insert_after_error(struct certificate_ocsp *ocsp)
* being at most 1 hour (with the current default values).
*/
replay_delay = MIN(SSL_OCSP_HTTP_ERR_REPLAY * (1 << ocsp->fail_count),
- SSL_OCSP_UPDATE_DELAY_MAX);
+ global_ssl.ocsp_update.delay_max);
if (ocsp->next_update.key < now.tv_sec + replay_delay)
ocsp->next_update.key = now.tv_sec + replay_delay;
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 2d4ededf1..1ce2483f3 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -132,7 +132,11 @@ struct global_ssl global_ssl = {
.extra_files = SSL_GF_ALL,
.extra_files_noext = 0,
#ifdef HAVE_SSL_KEYLOG
- .keylog = 0
+ .keylog = 0,
+#endif
+#ifndef OPENSSL_NO_OCSP
+ .ocsp_update.delay_max = SSL_OCSP_UPDATE_DELAY_MAX,
+ .ocsp_update.delay_min = SSL_OCSP_UPDATE_DELAY_MIN,
#endif
};