]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Make DoH ciphers configurable
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 15 Apr 2019 17:21:25 +0000 (19:21 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 17 Apr 2019 09:15:41 +0000 (11:15 +0200)
pdns/dnsdist-lua.cc
pdns/dnsdistdist/doh.cc
pdns/dnsdistdist/doh.hh
pdns/dnsdistdist/m4/dnsdist_with_libssl.m4

index bb68d91cb5b0c9758fb2d7630de0baba8c7abca9..1eec9e5937a1863a85ff3199e643b90ac1c38f83 100644 (file)
@@ -1677,6 +1677,12 @@ void setupLuaConfig(bool client)
       if (vars->count("idleTimeout")) {
         frontend->d_idleTimeout = boost::get<int>((*vars)["idleTimeout"]);
       }
+      if (vars->count("ciphers")) {
+        frontend->d_ciphers = boost::get<const string>((*vars)["ciphers"]);
+      }
+      if (vars->count("ciphersTLS13")) {
+        frontend->d_ciphers13 = boost::get<const string>((*vars)["ciphersTLS13"]);
+      }
     }
     g_dohlocals.push_back(frontend);
     auto cs = std::unique_ptr<ClientState>(new ClientState(frontend->d_local, true, false, 0, "", {}));
@@ -1871,6 +1877,11 @@ void setupLuaConfig(bool client)
               frontend->tlsFrontend->setupTLS();
             }
 #endif /* HAVE_DNS_OVER_TLS */
+#ifdef HAVE_DNS_OVER_HTTPS
+            if (frontend->dohFrontend) {
+              frontend->dohFrontend->reloadCertificate();
+            }
+#endif /* HAVE_DNS_OVER_HTTPS */
           }
           catch(const std::exception& e) {
             errlog("Error reloading certificates for frontend %s: %s", frontend->local.toStringWithPort(), e.what());
index c3a7409891e35b309491ff76e4c307f2310a3536..5456685ac2fb35614d9c6c54692c2444f03d106b 100644 (file)
@@ -45,7 +45,7 @@ using namespace std;
 // through the bowels of h2o
 struct DOHServerConfig
 {
-  DOHServerConfig(ClientState* cs_): cs(cs_), df(cs_->dohFrontend)
+  DOHServerConfig(uint32_t idleTimeout)
   {
     memset(&h2o_accept_ctx, 0, sizeof(h2o_accept_ctx));
 
@@ -60,7 +60,7 @@ struct DOHServerConfig
     }
 
     h2o_config_init(&h2o_config);
-    h2o_config.http2.idle_timeout = df->d_idleTimeout * 1000;
+    h2o_config.http2.idle_timeout = idleTimeout * 1000;
   }
 
   h2o_globalconf_t h2o_config;
@@ -86,7 +86,7 @@ static int processDOHQuery(DOHUnit* du)
       // we got closed meanwhile. XXX small race condition here
       return -1;
     }
-    DOHServerConfig* dsc = (DOHServerConfig*)du->req->conn->ctx->storage.entries[0].data;
+    DOHServerConfig* dsc = reinterpret_cast<DOHServerConfig*>(du->req->conn->ctx->storage.entries[0].data);
     ClientState& cs = *dsc->cs;
 
     if (du->query.size() < sizeof(dnsheader)) {
@@ -261,7 +261,7 @@ try
   h2o_socket_t* sock = req->conn->callbacks->get_socket(req->conn);
   ComboAddress remote;
   h2o_socket_getpeername(sock, reinterpret_cast<struct sockaddr*>(&remote));
-  DOHServerConfig* dsc = (DOHServerConfig*)req->conn->ctx->storage.entries[0].data;
+  DOHServerConfig* dsc = reinterpret_cast<DOHServerConfig*>(req->conn->ctx->storage.entries[0].data);
 
   if(auto tlsversion = h2o_socket_get_ssl_protocol_version(sock)) {
     if(!strcmp(tlsversion, "TLSv1.0"))
@@ -441,7 +441,7 @@ void dnsdistclient(int qsock, int rsock)
 static void on_dnsdist(h2o_socket_t *listener, const char *err)
 {
   DOHUnit *du = nullptr;
-  DOHServerConfig* dsc = (DOHServerConfig*)listener->data;
+  DOHServerConfig* dsc = reinterpret_cast<DOHServerConfig*>(listener->data);
   ssize_t got = recv(dsc->dohresponsepair[1], &du, sizeof(du), 0);
 
   if (got < 0) {
@@ -481,7 +481,7 @@ static void on_dnsdist(h2o_socket_t *listener, const char *err)
 
 static void on_accept(h2o_socket_t *listener, const char *err)
 {
-  DOHServerConfig* dsc = (DOHServerConfig*)listener->data;
+  DOHServerConfig* dsc = reinterpret_cast<DOHServerConfig*>(listener->data);
   h2o_socket_t *sock = nullptr;
 
   if (err != nullptr) {
@@ -501,16 +501,16 @@ static void on_accept(h2o_socket_t *listener, const char *err)
   h2o_accept(&dsc->h2o_accept_ctx, sock);
 }
 
-static int create_listener(const ComboAddress& addr, DOHServerConfig* dsc, int fd)
+static int create_listener(const ComboAddress& addr, std::shared_ptr<DOHServerConfig>& dsc, int fd)
 {
   auto sock = h2o_evloop_socket_create(dsc->h2o_ctx.loop, fd, H2O_SOCKET_FLAG_DONT_READ);
-  sock->data = (void*) dsc;
+  sock->data = dsc.get();
   h2o_socket_read_start(sock, on_accept);
 
   return 0;
 }
 
-static int setup_ssl(DOHServerConfig* dsc, const char *cert_file, const char *key_file, const char *ciphers)
+static int setup_ssl(std::shared_ptr<DOHServerConfig>& dsc, const std::string& cert_file, const std::string& key_file, const std::string& ciphers, const std::string& ciphers13)
 {
   SSL_load_error_strings();
   SSL_library_init();
@@ -525,20 +525,27 @@ static int setup_ssl(DOHServerConfig* dsc, const char *cert_file, const char *ke
 #endif
 
   /* load certificate and private key */
-  if (SSL_CTX_use_certificate_chain_file(dsc->h2o_accept_ctx.ssl_ctx, cert_file) != 1) {
-    fprintf(stderr, "an error occurred while trying to load server certificate file:%s\n", cert_file);
+  if (SSL_CTX_use_certificate_chain_file(dsc->h2o_accept_ctx.ssl_ctx, cert_file.c_str()) != 1) {
+    errlog("An error occurred while trying to load the DOH server certificate file: %s", cert_file);
     return -1;
   }
-  if (SSL_CTX_use_PrivateKey_file(dsc->h2o_accept_ctx.ssl_ctx, key_file, SSL_FILETYPE_PEM) != 1) {
-    fprintf(stderr, "an error occurred while trying to load private key file:%s\n", key_file);
+  if (SSL_CTX_use_PrivateKey_file(dsc->h2o_accept_ctx.ssl_ctx, key_file.c_str(), SSL_FILETYPE_PEM) != 1) {
+    errlog("An error occurred while trying to load the DOH server private key file: %s", key_file);
     return -1;
   }
 
-  if (SSL_CTX_set_cipher_list(dsc->h2o_accept_ctx.ssl_ctx, ciphers) != 1) {
-    fprintf(stderr, "ciphers could not be set: %s\n", ciphers);
+  if (SSL_CTX_set_cipher_list(dsc->h2o_accept_ctx.ssl_ctx, ciphers.c_str()) != 1) {
+    errlog("DOH ciphers could not be set: %s\n", ciphers);
     return -1;
   }
 
+#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
+  if (!ciphers13.empty() && SSL_CTX_set_ciphersuites(dsc->h2o_accept_ctx.ssl_ctx, ciphers13.c_str()) != 1) {
+    errlog("DOH TLS 1.3 ciphers could not be set: %s", ciphers13);
+    return -1;
+  }
+#endif /* HAVE_SSL_CTX_SET_CIPHERSUITES */
+
   h2o_ssl_register_alpn_protocols(dsc->h2o_accept_ctx.ssl_ctx, h2o_http2_alpn_protocols);
 
   return 0;
@@ -546,6 +553,14 @@ static int setup_ssl(DOHServerConfig* dsc, const char *cert_file, const char *ke
 
 void DOHFrontend::setup()
 {
+  d_dsc = std::make_shared<DOHServerConfig>(d_idleTimeout);
+
+    // we should probably make that hash, algorithm etc line configurable too
+  if (setup_ssl(d_dsc, d_certFile, d_keyFile,
+                d_ciphers.empty() ? "DEFAULT:!MD5:!DSS:!DES:!RC4:!RC2:!SEED:!IDEA:!NULL:!ADH:!EXP:!SRP:!PSK" : d_ciphers,
+                d_ciphers13) != 0) {
+    throw std::runtime_error("Failed to setup SSL/TLS for DoH listener");
+  }
 }
 
 // this is the entrypoint from dnsdist.cc
@@ -553,7 +568,9 @@ void dohThread(ClientState* cs)
 try
 {
   std::shared_ptr<DOHFrontend>& df = cs->dohFrontend;
-  auto dsc = new DOHServerConfig(cs);
+  auto& dsc = df->d_dsc;
+  dsc->cs = cs;
+  dsc->df = cs->dohFrontend;
 
   std::thread dnsdistThread(dnsdistclient, dsc->dohquerypair[1], dsc->dohresponsepair[0]);
   dnsdistThread.detach(); // gets us better error reporting
@@ -570,20 +587,15 @@ try
 
   // in this complicated way we insert the DOHServerConfig pointer in there
   h2o_vector_reserve(nullptr, &dsc->h2o_ctx.storage, 1);
-  dsc->h2o_ctx.storage.entries[0].data = (void*)dsc;
+  dsc->h2o_ctx.storage.entries[0].data = dsc.get();
   ++dsc->h2o_ctx.storage.size;
 
   auto sock = h2o_evloop_socket_create(dsc->h2o_ctx.loop, dsc->dohresponsepair[1], H2O_SOCKET_FLAG_DONT_READ);
-  sock->data = dsc;
+  sock->data = dsc.get();
 
   // this listens to responses from dnsdist to turn into http responses
   h2o_socket_read_start(sock, on_dnsdist);
 
-  // we should probably make that hash, algorithm etc line configurable too
-  if(setup_ssl(dsc, df->d_certFile.c_str(), df->d_keyFile.c_str(),
-                "DEFAULT:!MD5:!DSS:!DES:!RC4:!RC2:!SEED:!IDEA:!NULL:!ADH:!EXP:!SRP:!PSK") != 0)
-    throw std::runtime_error("Failed to setup SSL/TLS for DoH listener");
-
   // as one does
   dsc->h2o_accept_ctx.ctx = &dsc->h2o_ctx;
   dsc->h2o_accept_ctx.hosts = dsc->h2o_config.hosts;
index 58d1ae56b00d34d8c79e008e3d9338a21f90efc2..cf0c04fa7aa1014b0f6a52ac865e30faf5a17f10 100644 (file)
@@ -1,10 +1,15 @@
 #pragma once
 #include "iputils.hh"
 
+struct DOHServerConfig;
+
 struct DOHFrontend
 {
+  std::shared_ptr<DOHServerConfig> d_dsc{nullptr};
   std::string d_certFile;
   std::string d_keyFile;
+  std::string d_ciphers;
+  std::string d_ciphers13;
   ComboAddress d_local;
 
   uint32_t d_idleTimeout{30};             // HTTP idle timeout in seconds
@@ -25,6 +30,11 @@ struct DOHFrontend
   std::atomic<uint64_t> d_errorresponses; // dnsdist set 'error' on response
   std::atomic<uint64_t> d_validresponses; // valid responses sent out
 
+  void reloadCertificate()
+  {
+    // XXX: not implemented yet
+  }
+
 #ifndef HAVE_DNS_OVER_HTTPS
   void setup()
   {
index 79489448d68f13752a05f74dedbbcf6c2c1e0160..624a3d688f5ff20501355436c91937766340fab4 100644 (file)
@@ -13,6 +13,14 @@ AC_DEFUN([DNSDIST_WITH_LIBSSL], [
       PKG_CHECK_MODULES([LIBSSL], [libssl], [
         [HAVE_LIBSSL=1]
         AC_DEFINE([HAVE_LIBSSL], [1], [Define to 1 if you have OpenSSL libssl])
+        save_CFLAGS=$CFLAGS
+        save_LIBS=$LIBS
+        CFLAGS="$LIBSSL_CFLAGS $CFLAGS"
+        LIBS="$LIBSSL_LIBS $LIBS"
+        AC_CHECK_FUNCS([SSL_CTX_set_ciphersuites])
+        CFLAGS=$save_CFLAGS
+        LIBS=$save_LIBS
+
       ], [ : ])
     ])
   ])