if (vars.count("subjectName")) {
config.d_tlsSubjectName = boost::get<string>(vars.at("subjectName"));
}
+ else if (vars.count("subjectAddr")) {
+ try {
+ ComboAddress ca(boost::get<string>(vars.at("subjectAddr")));
+ config.d_tlsSubjectName = ca.toString();
+ config.d_tlsSubjectIsAddr = true;
+ }
+ catch (const std::exception& e) {
+ errlog("Error creating new server: downstream subjectAddr value must be a valid IP address");
+ return std::shared_ptr<DownstreamState>();
+ }
+ }
if (vars.count("tls")) {
config.d_tlsParams.d_provider = boost::get<string>(vars.at("tls"));
uint8_t maxCheckFailures{1};
uint8_t minRiseSuccesses{1};
Availability availability{Availability::Auto};
+ bool d_tlsSubjectIsAddr{false};
bool mustResolve{false};
bool useECS{false};
bool useProxyProtocol{false};
}
time_t now = time(nullptr);
- auto handler = std::make_unique<TCPIOHandler>(ds->d_config.d_tlsSubjectName, sock.releaseHandle(), timeval{ds->d_config.checkTimeout, 0}, ds->d_tlsCtx, now);
+ auto handler = std::make_unique<TCPIOHandler>(ds->d_config.d_tlsSubjectName, ds->d_config.d_tlsSubjectIsAddr, sock.releaseHandle(), timeval{ds->d_config.checkTimeout, 0}, ds->d_tlsCtx, now);
handler->connect(ds->d_config.tcpFastOpen, ds->d_config.remote, timeval{ds->d_config.checkTimeout, 0});
return true;
}
extension."
*/
config.d_tlsSubjectName = backend.d_ds->d_config.remote.toString();
+ config.d_tlsSubjectIsAddr = true;
}
if (!backend.d_poolAfterUpgrade.empty()) {
}
else {
time_t now = time(nullptr);
- data->d_tcpHandler = std::make_unique<TCPIOHandler>(ds->d_config.d_tlsSubjectName, sock.releaseHandle(), timeval{ds->d_config.checkTimeout,0}, ds->d_tlsCtx, now);
+ data->d_tcpHandler = std::make_unique<TCPIOHandler>(ds->d_config.d_tlsSubjectName, ds->d_config.d_tlsSubjectIsAddr, sock.releaseHandle(), timeval{ds->d_config.checkTimeout,0}, ds->d_tlsCtx, now);
data->d_ioState = std::make_unique<IOStateHandler>(*mplexer, data->d_tcpHandler->getDescriptor());
if (ds->d_tlsCtx) {
try {
socket->setNonBlocking();
gettimeofday(&d_connectionStartTime, nullptr);
- auto handler = std::make_unique<TCPIOHandler>(d_ds->d_config.d_tlsSubjectName, socket->releaseHandle(), timeval{0,0}, d_ds->d_tlsCtx, d_connectionStartTime.tv_sec);
+ auto handler = std::make_unique<TCPIOHandler>(d_ds->d_config.d_tlsSubjectName, d_ds->d_config.d_tlsSubjectIsAddr, socket->releaseHandle(), timeval{0,0}, d_ds->d_tlsCtx, d_connectionStartTime.tv_sec);
if (!tlsSession && d_ds->d_tlsCtx) {
tlsSession = g_sessionCache.getSession(d_ds->getID(), d_connectionStartTime.tv_sec);
}
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`` and ``autoUpgradePool`` to server_table.
+ Added ``autoUpgrade``, ``autoUpgradeDoHKey``, ``autoUpgradeInterval``, ``autoUpgradeKeep``, ``autoUpgradePool`` and ``subjectAddr`` to server_table.
Add a new backend server. Call this function with either a string::
caStore=STRING, -- Specifies the path to the CA certificate file, in PEM format, to use to check the certificate presented by the backend. Default is an empty string, which means to use the system CA store. Note that this directive is only used if ``validateCertificates`` is set.
ciphers=STRING, -- The TLS ciphers to use. The exact format depends on the provider used. When the OpenSSL provider is used, ciphers for TLS 1.3 must be specified via ``ciphersTLS13``.
ciphersTLS13=STRING, -- The ciphers to use for TLS 1.3, when the OpenSSL provider is used. When the GnuTLS provider is used, ``ciphers`` applies regardless of the TLS protocol and this setting is not used.
- subjectName=STRING, -- The subject name passed in the SNI value of the TLS handshake, and against which to validate the certificate presented by the backend. Default is empty.
+ subjectName=STRING, -- The subject name passed in the SNI value of the TLS handshake, and against which to validate the certificate presented by the backend. Default is empty. If set this value supersedes any ``subjectAddr`` one.
+ subjectAddr=STRING, -- The subject IP address passed in the SNI value of the TLS handshake, and against which to validate the certificate presented by the backend. Default is empty.
validateCertificates=BOOL,-- Whether the certificate presented by the backend should be validated against the CA store (see ``caStore``). Default is true.
dohPath=STRING, -- Enable DNS over HTTPS communication for this backend, using POST queries to the HTTP host supplied as ``subjectName`` and the HTTP path supplied in this parameter.
addXForwardedHeaders=BOOL,-- Whether to add X-Forwarded-For, X-Forwarded-Port and X-Forwarded-Proto headers to a DNS over HTTPS backend.
return std::make_unique<MockupTLSConnection>(socket);
}
- std::unique_ptr<TLSConnection> getClientConnection(const std::string& host, int socket, const struct timeval& timeout) override
+ std::unique_ptr<TLSConnection> getClientConnection(const std::string& host, bool hostIsAddr, int socket, const struct timeval& timeout) override
{
return std::make_unique<MockupTLSConnection>(socket, true, d_needProxyProtocol);
}
return std::make_unique<MockupTLSConnection>(socket);
}
- std::unique_ptr<TLSConnection> getClientConnection(const std::string& host, int socket, const struct timeval& timeout) override
+ std::unique_ptr<TLSConnection> getClientConnection(const std::string& host, bool hostIsAddr, int socket, const struct timeval& timeout) override
{
return std::make_unique<MockupTLSConnection>(socket, true);
}
dnsOverTLS = false;
}
}
- connection.d_handler = std::make_shared<TCPIOHandler>(nsName, s.releaseHandle(), timeout, tlsCtx, now.tv_sec);
+ connection.d_handler = std::make_shared<TCPIOHandler>(nsName, false, s.releaseHandle(), timeout, tlsCtx, now.tv_sec);
// Returned state ignored
// This can throw an exception, retry will need to happen at higher level
connection.d_handler->tryConnect(SyncRes::s_tcp_fast_open_connect, ip);
{
g_networkTimeoutMsec / 1000, static_cast<suseconds_t>(g_networkTimeoutMsec) % 1000 * 1000
};
- auto handler = std::make_shared<TCPIOHandler>("", s.releaseHandle(), timeout, tlsCtx, time(nullptr));
+ auto handler = std::make_shared<TCPIOHandler>("", false, s.releaseHandle(), timeout, tlsCtx, time(nullptr));
handler->tryConnect(SyncRes::s_tcp_fast_open_connect, remote); // we do the connect so the first attempt happens while we gather stats
if (msg.empty()) {
Socket sock(dest.sin4.sin_family, SOCK_STREAM);
sock.setNonBlocking();
setTCPNoDelay(sock.getHandle()); // disable NAGLE, which does not play nicely with delayed ACKs
- TCPIOHandler handler(subjectName, sock.releaseHandle(), timeout, tlsCtx, time(nullptr));
+ TCPIOHandler handler(subjectName, false, sock.releaseHandle(), timeout, tlsCtx, time(nullptr));
handler.connect(fastOpen, dest, timeout);
// we are writing the proxyheader inside the TLS connection. Is that right?
if (proxyheader.size() > 0 && handler.write(proxyheader.data(), proxyheader.size(), timeout) != proxyheader.size()) {
}
/* client-side connection */
- OpenSSLTLSConnection(const std::string& hostname, int socket, const struct timeval& timeout, std::shared_ptr<SSL_CTX>& tlsCtx): d_tlsCtx(tlsCtx), d_conn(std::unique_ptr<SSL, void(*)(SSL*)>(SSL_new(tlsCtx.get()), SSL_free)), d_hostname(hostname), d_timeout(timeout)
+ OpenSSLTLSConnection(const std::string& hostname, bool hostIsAddr, int socket, const struct timeval& timeout, std::shared_ptr<SSL_CTX>& tlsCtx): d_tlsCtx(tlsCtx), d_conn(std::unique_ptr<SSL, void(*)(SSL*)>(SSL_new(tlsCtx.get()), SSL_free)), d_hostname(hostname), d_timeout(timeout)
{
d_socket = socket;
throw std::runtime_error("Error setting TLS SNI to " + d_hostname);
}
-#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && HAVE_SSL_SET_HOSTFLAGS // grrr libressl
- SSL_set_hostflags(d_conn.get(), X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
- if (SSL_set1_host(d_conn.get(), d_hostname.c_str()) != 1) {
- throw std::runtime_error("Error setting TLS hostname for certificate validation");
+ if (hostIsAddr) {
+#if (OPENSSL_VERSION_NUMBER >= 0x10002000L)
+ X509_VERIFY_PARAM *param = SSL_get0_param(d_conn.get());
+ /* Enable automatic IP checks */
+ X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+ if (X509_VERIFY_PARAM_set1_ip_asc(param, d_hostname.c_str()) != 1) {
+ throw std::runtime_error("Error setting TLS IP for certificate validation");
+ }
+#else
+ /* no validation for you, see https://wiki.openssl.org/index.php/Hostname_validation */
+#endif
}
+ else {
+#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && HAVE_SSL_SET_HOSTFLAGS // grrr libressl
+ SSL_set_hostflags(d_conn.get(), X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+ if (SSL_set1_host(d_conn.get(), d_hostname.c_str()) != 1) {
+ throw std::runtime_error("Error setting TLS hostname for certificate validation");
+ }
#elif (OPENSSL_VERSION_NUMBER >= 0x10002000L)
- X509_VERIFY_PARAM *param = SSL_get0_param(d_conn.get());
- /* Enable automatic hostname checks */
- X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
- if (X509_VERIFY_PARAM_set1_host(param, d_hostname.c_str(), d_hostname.size()) != 1) {
- throw std::runtime_error("Error setting TLS hostname for certificate validation");
- }
+ X509_VERIFY_PARAM *param = SSL_get0_param(d_conn.get());
+ /* Enable automatic hostname checks */
+ X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+ if (X509_VERIFY_PARAM_set1_host(param, d_hostname.c_str(), d_hostname.size()) != 1) {
+ throw std::runtime_error("Error setting TLS hostname for certificate validation");
+ }
#else
- /* no hostname validation for you, see https://wiki.openssl.org/index.php/Hostname_validation */
+ /* no hostname validation for you, see https://wiki.openssl.org/index.php/Hostname_validation */
#endif
+ }
+
SSL_set_ex_data(d_conn.get(), s_tlsConnIndex, this);
}
return std::make_unique<OpenSSLTLSConnection>(socket, timeout, d_feContext);
}
- std::unique_ptr<TLSConnection> getClientConnection(const std::string& host, int socket, const struct timeval& timeout) override
+ std::unique_ptr<TLSConnection> getClientConnection(const std::string& host, bool hostIsAddr, int socket, const struct timeval& timeout) override
{
- return std::make_unique<OpenSSLTLSConnection>(host, socket, timeout, d_tlsCtx);
+ return std::make_unique<OpenSSLTLSConnection>(host, hostIsAddr, socket, timeout, d_tlsCtx);
}
void rotateTicketsKey(time_t now) override
return entry;
}
- std::unique_ptr<TLSConnection> getClientConnection(const std::string& host, int socket, const struct timeval& timeout) override
+ std::unique_ptr<TLSConnection> getClientConnection(const std::string& host, bool, int socket, const struct timeval& timeout) override
{
auto creds = getPerThreadCredentials(d_contextParameters->d_validateCertificates, d_contextParameters->d_caStore);
auto connection = std::make_unique<GnuTLSConnection>(host, socket, timeout, creds, d_priorityCache, d_validateCerts);
}
virtual ~TLSCtx() {}
virtual std::unique_ptr<TLSConnection> getConnection(int socket, const struct timeval& timeout, time_t now) = 0;
- virtual std::unique_ptr<TLSConnection> getClientConnection(const std::string& host, int socket, const struct timeval& timeout) = 0;
+ virtual std::unique_ptr<TLSConnection> getClientConnection(const std::string& host, bool hostIsAddr, int socket, const struct timeval& timeout) = 0;
virtual void rotateTicketsKey(time_t now) = 0;
virtual void loadTicketsKeys(const std::string& file)
{
public:
enum class Type : uint8_t { Client, Server };
- TCPIOHandler(const std::string& host, int socket, const struct timeval& timeout, std::shared_ptr<TLSCtx> ctx, time_t now): d_socket(socket)
+ TCPIOHandler(const std::string& host, bool hostIsAddr, int socket, const struct timeval& timeout, std::shared_ptr<TLSCtx> ctx, time_t now): d_socket(socket)
{
if (ctx) {
- d_conn = ctx->getClientConnection(host, d_socket, timeout);
+ d_conn = ctx->getClientConnection(host, hostIsAddr, d_socket, timeout);
}
}
g_networkTimeoutMsec / 1000, static_cast<suseconds_t>(g_networkTimeoutMsec) % 1000 * 1000
};
std::shared_ptr<TLSCtx> tlsCtx{nullptr};
- auto handler = std::make_shared<TCPIOHandler>("", client->releaseHandle(), timeout, tlsCtx, time(nullptr));
+ auto handler = std::make_shared<TCPIOHandler>("", false, client->releaseHandle(), timeout, tlsCtx, time(nullptr));
PacketBuffer data;
try {