diff options
author | Remi Tricot-Le Breton <rlebreton@haproxy.com> | 2023-02-28 17:46:29 +0100 |
---|---|---|
committer | William Lallemand <wlallemand@haproxy.org> | 2023-03-02 15:37:23 +0100 |
commit | 5843237993d4f53e3ccfb4dbedf35e2219c634eb (patch) | |
tree | c7cf974594c6c506bc086db2bbc20935e5ba35e9 | |
parent | 9c4437d0241a8d2e29b1693e0a8d7e1b2894e64e (diff) | |
download | haproxy-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.txt | 27 | ||||
-rw-r--r-- | include/haproxy/ssl_ocsp-t.h | 5 | ||||
-rw-r--r-- | include/haproxy/ssl_sock-t.h | 7 | ||||
-rw-r--r-- | src/cfgparse-ssl.c | 57 | ||||
-rw-r--r-- | src/ssl_ocsp.c | 10 | ||||
-rw-r--r-- | src/ssl_sock.c | 6 |
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 }; |