getOptionalValue<bool>(vars, "releaseBuffers", config.d_releaseBuffers);
getOptionalValue<bool>(vars, "enableRenegotiation", config.d_enableRenegotiation);
getOptionalValue<bool>(vars, "tlsAsyncMode", config.d_asyncMode);
+ getOptionalValue<bool>(vars, "ktls", config.d_ktls);
}
#endif // defined(HAVE_DNS_OVER_TLS) || defined(HAVE_DNS_OVER_HTTPS)
getOptionalValue<bool>(vars, "validateCertificates", config.d_tlsParams.d_validateCertificates);
getOptionalValue<bool>(vars, "releaseBuffers", config.d_tlsParams.d_releaseBuffers);
getOptionalValue<bool>(vars, "enableRenegotiation", config.d_tlsParams.d_enableRenegotiation);
+ getOptionalValue<bool>(vars, "ktls", config.d_tlsParams.d_ktls);
getOptionalValue<std::string>(vars, "subjectName", config.d_tlsSubjectName);
if (getOptionalValue<std::string>(vars, "subjectAddr", valueStr) > 0) {
Since 1.8.0, incoming DNS over TLS might also benefit from experimental support for TLS acceleration engines, like Intel QAT. See :func:`loadTLSEngine`, and the `tlsAsyncMode` parameter of :func:`addTLSLocal` for more information.
+Incoming and outgoing DNS over TLS, as well as outgoing DNS over HTTPS, might benefit from experimental support kernel-accelerated TLS on Linux, when supported by the kernel and OpenSSL. See the `ktls` options on :func:`addTLSLocal` and :func:`newServer` for more information. Kernel support for kTLS might be verified by looking at the counters in ``/proc/net/tls_stat``. Note that:
+
+ * supported ciphers depend on the exact kernel version used. ``TLS_AES_128_GCM_SHA256`` might be a good option for testing purpose since it was supported pretty early
+ * as of OpenSSL 3.0.7, kTLS can only be used for sending TLS 1.3 packets, not receiving them. Both sending and receiving packets should be working for TLS 1.2.
+
+
Rules and Lua
-------------
``tlsAsyncMode`` option added.
.. versionchanged:: 1.8.0
``certFile`` now accepts a TLSCertificate object or a list of such objects (see :func:`newTLSCertificate`).
- ``additionalAddresses`` and ``ignoreTLSConfigurationErrors`` options added.
+ ``additionalAddresses``, ``ignoreTLSConfigurationErrors`` and ``ktls`` options added.
Listen on the specified address and TCP port for incoming DNS over TLS connections, presenting the specified X.509 certificate.
* ``tlsAsyncMode=false``: bool - Whether to enable experimental asynchronous TLS I/O operations if OpenSSL is used as the TLS implementation and an asynchronous capable SSL engine (or provider) is loaded. See also :func:`loadTLSEngine` or :func:`loadTLSProvider` to load the engine (or provider).
* ``additionalAddresses``: list - List of additional addresses (with port) to listen on. Using this option instead of creating a new frontend for each address avoids the creation of new thread and Frontend objects, reducing the memory usage. The drawback is that there will be a single set of metrics for all addresses.
* ``ignoreTLSConfigurationErrors=false``: bool - Ignore TLS configuration errors (such as invalid certificate path) and just issue a warning instead of aborting the whole process
+ * ``ktls=false``: bool - Whether to enable the experimental kernel TLS support on Linux, if both the kernel and the OpenSSL library support it. Default is false.
.. function:: setLocal(address[, options])
Added ``addXForwardedHeaders``, ``caStore``, ``checkTCP``, ``ciphers``, ``ciphers13``, ``dohPath``, ``enableRenegotiation``, ``releaseBuffers``, ``subjectName``, ``tcpOnly``, ``tls`` and ``validateCertificates`` to server_table.
.. versionchanged:: 1.8.0
- Added ``autoUpgrade``, ``autoUpgradeDoHKey``, ``autoUpgradeInterval``, ``autoUpgradeKeep``, ``autoUpgradePool``, ``maxConcurrentTCPConnections``, ``subjectAddr``, ``lazyHealthCheckSampleSize``, ``lazyHealthCheckMinSampleCount``, ``lazyHealthCheckThreshold``, ``lazyHealthCheckFailedInterval``, ``lazyHealthCheckMode``, ``lazyHealthCheckUseExponentialBackOff``, ``lazyHealthCheckMaxBackOff``, ``lazyHealthCheckWhenUpgraded`` and ``healthCheckMode`` to server_table.
+ Added ``autoUpgrade``, ``autoUpgradeDoHKey``, ``autoUpgradeInterval``, ``autoUpgradeKeep``, ``autoUpgradePool``, ``maxConcurrentTCPConnections``, ``subjectAddr``, ``lazyHealthCheckSampleSize``, ``lazyHealthCheckMinSampleCount``, ``lazyHealthCheckThreshold``, ``lazyHealthCheckFailedInterval``, ``lazyHealthCheckMode``, ``lazyHealthCheckUseExponentialBackOff``, ``lazyHealthCheckMaxBackOff``, ``lazyHealthCheckWhenUpgraded``, ``healthCheckMode`` and ``ktls`` to server_table.
Add a new backend server. Call this function with either a string::
lazyHealthCheckThreshold=NUM, -- The threshold, as a percentage, of queries that should fail for the 'lazy' health-check to be triggered when ``healthCheckMode`` is set to ``lazy``. The default is 20 which means 20% of the last ``lazyHealthCheckSampleSize`` queries should fail for a health-check to be triggered.
lazyHealthCheckUseExponentialBackOff=BOOL, -- Whether the 'lazy' health-check should use an exponential back-off instead of a fixed value, between health-check probes. The default is false which means that after a backend has been moved to the 'down' state health-check probes are sent every ``lazyHealthCheckFailedInterval`` seconds. When set to true, the delay between each probe starts at ``lazyHealthCheckFailedInterval`` seconds and double between every probe, capped at ``lazyHealthCheckMaxBackOff`` seconds.
lazyHealthCheckMaxBackOff=NUM, -- This value, in seconds, caps the time between two health-check queries when ``lazyHealthCheckUseExponentialBackOff`` is set to true. The default is 3600 which means that at most one hour will pass between two health-check queries.
- lazyHealthCheckWhenUpgraded=BOOL -- Whether the auto-upgraded version of this backend (see ``autoUpgrade``) should use the lazy health-checking mode. Default is false, which means it will use the regular health-checking mode.
+ lazyHealthCheckWhenUpgraded=BOOL, -- Whether the auto-upgraded version of this backend (see ``autoUpgrade``) should use the lazy health-checking mode. Default is false, which means it will use the regular health-checking mode.
+ ktls=BOOL, -- Whether to enable the experimental kernel TLS support on Linux, if both the kernel and the OpenSSL library support it. Default is false. Currently both DoT and DoH backend support this option.
})
:param str server_string: A simple IP:PORT string.
#endif /* HAVE_SSL_CTX_SET_NUM_TICKETS */
}
+ if (config.d_ktls) {
+#ifdef SSL_OP_ENABLE_KTLS
+ sslOptions |= SSL_OP_ENABLE_KTLS;
+#endif /* SSL_OP_ENABLE_KTLS */
+ }
+
if (config.d_sessionTimeout > 0) {
SSL_CTX_set_timeout(ctx.get(), config.d_sessionTimeout);
}
bool d_enableRenegotiation{false};
/* enable TLS async mode, if supported by any engine */
bool d_asyncMode{false};
+ /* enable kTLS mode, if supported */
+ bool d_ktls{false};
};
struct TLSErrorCounters
IOState tryWrite(const PacketBuffer& buffer, size_t& pos, size_t toWrite) override
{
+ if (!d_feContext && !d_connected) {
+ if (d_ktls) {
+ /* work-around to get kTLS to be started, as we cannot do that until after the socket has been connected */
+ SSL_set_fd(d_conn.get(), SSL_get_fd(d_conn.get()));
+ }
+ }
+
do {
int res = SSL_write(d_conn.get(), reinterpret_cast<const char *>(&buffer.at(pos)), static_cast<int>(toWrite - pos));
if (res <= 0) {
}
}
while (pos < toWrite);
+
+ if (!d_connected) {
+ d_connected = true;
+ }
+
return IOState::Done;
}
d_tlsSessions.push_back(std::make_unique<OpenSSLSession>(std::unique_ptr<SSL_SESSION, void (*)(SSL_SESSION*)>(session, SSL_SESSION_free)));
}
+ void enableKTLS()
+ {
+ d_ktls = true;
+ }
+
static int s_tlsConnIndex;
private:
std::unique_ptr<SSL, void(*)(SSL*)> d_conn;
std::string d_hostname;
struct timeval d_timeout;
+ bool d_connected{false};
+ bool d_ktls{false};
};
std::atomic_flag OpenSSLTLSConnection::s_initTLSConnIndex = ATOMIC_FLAG_INIT;
#endif
}
+ if (params.d_ktls) {
+#ifdef SSL_OP_ENABLE_KTLS
+ sslOptions |= SSL_OP_ENABLE_KTLS;
+ d_ktls = true;
+#endif /* SSL_OP_ENABLE_KTLS */
+ }
+
registerOpenSSLUser();
#ifdef HAVE_TLS_CLIENT_METHOD
std::unique_ptr<TLSConnection> getClientConnection(const std::string& host, bool hostIsAddr, int socket, const struct timeval& timeout) override
{
- return std::make_unique<OpenSSLTLSConnection>(host, hostIsAddr, socket, timeout, d_tlsCtx);
+ auto conn = std::make_unique<OpenSSLTLSConnection>(host, hostIsAddr, socket, timeout, d_tlsCtx);
+ if (d_ktls) {
+ conn->enableKTLS();
+ }
+ return conn;
}
void rotateTicketsKey(time_t now) override
std::shared_ptr<OpenSSLFrontendContext> d_feContext{nullptr};
std::shared_ptr<SSL_CTX> d_tlsCtx{nullptr}; // client context, on a server-side the context is stored in d_feContext->d_tlsCtx
bool (*d_nextProtocolSelectCallback)(unsigned char** out, unsigned char* outlen, const unsigned char* in, unsigned int inlen){nullptr};
+ bool d_ktls{false};
};
#endif /* HAVE_LIBSSL */
bool d_validateCertificates{true};
bool d_releaseBuffers{true};
bool d_enableRenegotiation{false};
+ bool d_ktls{false};
};
std::shared_ptr<TLSCtx> getTLSContext(const TLSContextParameters& params);