if (vars->count("ciphersTLS13")) {
frontend->d_ciphers13 = boost::get<const string>((*vars)["ciphersTLS13"]);
}
+ if (vars->count("minTLSVersion")) {
+ frontend->d_minTLSVersion = libssl_tls_version_from_string(boost::get<const string>((*vars)["minTLSVersion"]));
+ }
if (vars->count("serverTokens")) {
frontend->d_serverTokens = boost::get<const string>((*vars)["serverTokens"]);
}
frontend->d_ciphers13 = boost::get<const string>((*vars)["ciphersTLS13"]);
}
+#ifdef HAVE_LIBSSL
+ if (vars->count("minTLSVersion")) {
+ frontend->d_minTLSVersion = libssl_tls_version_from_string(boost::get<const string>((*vars)["minTLSVersion"]));
+ }
+#endif /* HAVE_LIBSSL */
+
if (vars->count("ticketKeyFile")) {
frontend->d_ticketKeyFile = boost::get<const string>((*vars)["ticketKeyFile"]);
}
* ``serverTokens``: str - The content of the Server: HTTP header returned by dnsdist. The default is "h2o/dnsdist".
* ``customResponseHeaders={}``: table - Set custom HTTP header(s) returned by dnsdist.
* ``ocspResponses``: list - List of files containing OCSP responses, in the same order than the certificates and keys, that will be used to provide OCSP stapling responses.
+ * ``minTLSVersion``: str - Minimum version of the TLS protocol to support. Possible values are 'tls-1.0', 'tls-1.1', 'tls-1.2' and 'tls-1.3'.
.. function:: addTLSLocal(address, certFile(s), keyFile(s) [, options])
.. versionchanged:: 1.3.3
``numberOfStoredSessions`` option added.
.. versionchanged:: 1.4.0
- ``ciphersTLS13`` and ``ocspResponses`` options added.
+ ``ciphersTLS13``, ``minTLSVersion`` and ``ocspResponses`` options added.
Listen on the specified address and TCP port for incoming DNS over TLS connections, presenting the specified X.509 certificate.
* ``sessionTickets``: bool - Whether session resumption via session tickets is enabled. Default is true, meaning tickets are enabled.
* ``numberOfStoredSessions``: int - The maximum number of sessions kept in memory at the same time. At this time this is only supported by the OpenSSL provider, as stored sessions are not supported with the GnuTLS one. Default is 20480. Setting this value to 0 disables stored session entirely.
* ``ocspResponses``: list - List of files containing OCSP responses, in the same order than the certificates and keys, that will be used to provide OCSP stapling responses.
+ * ``minTLSVersion``: str - Minimum version of the TLS protocol to support. Possible values are 'tls-1.0', 'tls-1.1', 'tls-1.2' and 'tls-1.3'. Note that this value is ignored when the GnuTLS provider is in use, and the ``ciphers`` option should be set accordingly instead. For example, 'NORMAL:!VERS-TLS1.0:!VERS-TLS1.1' will disable TLS 1.0 and 1.1.
.. function:: setLocal(address[, options])
return libssl_ocsp_stapling_callback(ssl, *ocspMap);
}
-static std::unique_ptr<SSL_CTX, void(*)(SSL_CTX*)> getTLSContext(const std::vector<std::pair<std::string, std::string>>& pairs, const std::string& ciphers, const std::string& ciphers13, const std::vector<std::string>& ocspFiles, std::map<int, std::string>& ocspResponses)
+static std::unique_ptr<SSL_CTX, void(*)(SSL_CTX*)> getTLSContext(const std::vector<std::pair<std::string, std::string>>& pairs, const std::string& ciphers, const std::string& ciphers13, LibsslTLSVersion minTLSVersion, const std::vector<std::string>& ocspFiles, std::map<int, std::string>& ocspResponses)
{
auto ctx = std::unique_ptr<SSL_CTX, void(*)(SSL_CTX*)>(SSL_CTX_new(SSLv23_server_method()), SSL_CTX_free);
SSL_OP_SINGLE_ECDH_USE;
SSL_CTX_set_options(ctx.get(), sslOptions);
+ libssl_set_min_tls_version(ctx, minTLSVersion);
#ifdef SSL_CTX_set_ecdh_auto
SSL_CTX_set_ecdh_auto(ctx.get(), 1);
auto tlsCtx = getTLSContext(dsc.df->d_certKeyPairs,
dsc.df->d_ciphers,
dsc.df->d_ciphers13,
+ dsc.df->d_minTLSVersion,
dsc.df->d_ocspFiles,
ctx.d_ocspResponses);
auto tlsCtx = getTLSContext(d_certKeyPairs,
d_ciphers,
d_ciphers13,
+ d_minTLSVersion,
d_ocspFiles,
d_dsc->accept_ctx->d_ocspResponses);
}
#endif /* HAVE_OCSP_BASIC_SIGN */
+LibsslTLSVersion libssl_tls_version_from_string(const std::string& str)
+{
+ if (str == "tls1.0") {
+ return LibsslTLSVersion::TLS10;
+ }
+ if (str == "tls1.1") {
+ return LibsslTLSVersion::TLS11;
+ }
+ if (str == "tls1.2") {
+ return LibsslTLSVersion::TLS12;
+ }
+ if (str == "tls1.3") {
+ return LibsslTLSVersion::TLS13;
+ }
+ throw std::runtime_error("Unknown TLS version '" + str);
+}
+
+bool libssl_set_min_tls_version(std::unique_ptr<SSL_CTX, void(*)(SSL_CTX*)>& ctx, LibsslTLSVersion version)
+{
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL && !defined LIBRESSL_VERSION_NUMBER)
+ /* these functions have been introduced in 1.1.0, and the use of SSL_OP_NO_* is deprecated */
+ int vers;
+ switch(version) {
+ case LibsslTLSVersion::TLS10:
+ vers = TLS1_VERSION;
+ break;
+ case LibsslTLSVersion::TLS11:
+ vers = TLS1_1_VERSION;
+ break;
+ case LibsslTLSVersion::TLS12:
+ vers = TLS1_2_VERSION;
+ break;
+ case LibsslTLSVersion::TLS13:
+ vers = TLS1_3_VERSION;
+ break;
+ default:
+ return false;
+ }
+
+ if (SSL_CTX_set_min_proto_version(ctx.get(), vers) != 1) {
+ return false;
+ }
+ return true;
+#else
+ long vers = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
+ switch(version) {
+ case LibsslTLSVersion::TLS10:
+ break;
+ case LibsslTLSVersion::TLS11:
+ vers |= SSL_OP_NO_TLSv1;
+ break;
+ case LibsslTLSVersion::TLS12:
+ vers |= SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
+ break;
+ case LibsslTLSVersion::TLS13:
+ vers |= SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2;
+ break;
+ default:
+ return false;
+ }
+
+ long options = SSL_CTX_get_options(ctx.get());
+ SSL_CTX_set_options(ctx.get(), options | vers);
+ return true;
+#endif
+}
+
#endif /* HAVE_LIBSSL */
bool libssl_generate_ocsp_response(const std::string& certFile, const std::string& caCert, const std::string& caKey, const std::string& outFile, int ndays, int nmin);
#endif
+enum class LibsslTLSVersion { TLS10, TLS11, TLS12, TLS13 };
+
+LibsslTLSVersion libssl_tls_version_from_string(const std::string& str);
+bool libssl_set_min_tls_version(std::unique_ptr<SSL_CTX, void(*)(SSL_CTX*)>& ctx, LibsslTLSVersion version);
+
#endif /* HAVE_LIBSSL */
SSL_CTX_set_tlsext_ticket_key_cb(d_tlsCtx.get(), &OpenSSLTLSIOCtx::ticketKeyCb);
SSL_CTX_set_ex_data(d_tlsCtx.get(), s_ticketsKeyIndex, this);
SSL_CTX_set_options(d_tlsCtx.get(), sslOptions);
+ libssl_set_min_tls_version(d_tlsCtx, fe.d_minTLSVersion);
#if defined(SSL_CTX_set_ecdh_auto)
SSL_CTX_set_ecdh_auto(d_tlsCtx.get(), 1);
#endif
#pragma once
#include "iputils.hh"
+#include "libssl.hh"
struct DOHServerConfig;
std::string d_ciphers;
std::string d_ciphers13;
std::string d_serverTokens{"h2o/dnsdist"};
+ LibsslTLSVersion d_minTLSVersion{LibsslTLSVersion::TLS10};
std::vector<std::pair<std::string, std::string>> d_customResponseHeaders;
ComboAddress d_local;
#pragma once
#include <memory>
+#include "libssl.hh"
#include "misc.hh"
enum class IOState { Done, NeedRead, NeedWrite };
size_t d_maxStoredSessions{20480};
time_t d_ticketsKeyRotationDelay{43200};
uint8_t d_numberOfTicketsKeys{5};
+ LibsslTLSVersion d_minTLSVersion{LibsslTLSVersion::TLS10};
+
bool d_enableTickets{true};
private: