]> granicus.if.org Git - pdns/commitdiff
dnsdist: Add metrics about TLS versions with DNS over TLS
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 7 Oct 2019 14:00:59 +0000 (16:00 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 7 Oct 2019 14:00:59 +0000 (16:00 +0200)
pdns/dnsdist-carbon.cc
pdns/dnsdist-lua-inspection.cc
pdns/dnsdist-lua.cc
pdns/dnsdist-tcp.cc
pdns/dnsdist-web.cc
pdns/dnsdist.hh
pdns/dnsdistdist/doh.cc
pdns/dnsdistdist/tcpiohandler.cc
pdns/doh.hh
pdns/libssl.hh
pdns/tcpiohandler.hh

index 41fc44f64d4ba4c7f8b7d7b7a0499f326a6c39d9..755832815b929a4dac3f1bf416b1993f59f73dfe 100644 (file)
@@ -132,6 +132,11 @@ try
           str<<base<<"tcpavgconnectionduration" << ' '<< front->tcpAvgConnectionDuration.load() << " " << now << "\r\n";
           str<<base<<"tlsnewsessions" << ' ' << front->tlsNewSessions.load() << " " << now << "\r\n";
           str<<base<<"tlsresumptions" << ' ' << front->tlsResumptions.load() << " " << now << "\r\n";
+          str<<base<<"tls10-queries" << ' ' << front->tls10queries.load() << " " << now << "\r\n";
+          str<<base<<"tls11-queries" << ' ' << front->tls11queries.load() << " " << now << "\r\n";
+          str<<base<<"tls12-queries" << ' ' << front->tls12queries.load() << " " << now << "\r\n";
+          str<<base<<"tls13-queries" << ' ' << front->tls13queries.load() << " " << now << "\r\n";
+          str<<base<<"tls-unknown-queries" << ' ' << front->tlsUnknownqueries.load() << " " << now << "\r\n";
         }
 
         auto localPools = g_pools.getLocal();
@@ -192,11 +197,6 @@ try
               {"http2-502-responses", doh->d_http2Stats.d_nb502Responses},
               {"http1-other-responses", doh->d_http1Stats.d_nbOtherResponses},
               {"http2-other-responses", doh->d_http2Stats.d_nbOtherResponses},
-              {"tls10-queries", doh->d_tls10queries},
-              {"tls11-queries", doh->d_tls11queries},
-              {"tls12-queries", doh->d_tls12queries},
-              {"tls13-queries", doh->d_tls13queries},
-              {"tls-unknown-queries", doh->d_tlsUnknownqueries},
               {"get-queries", doh->d_getqueries},
               {"post-queries", doh->d_postqueries},
               {"bad-requests", doh->d_badrequests},
index 1a3cd227f182d95efea4ea3fdbb9cd48529bae30..ebad23400bce8fd1569dcb74e82e53b44b651bc0 100644 (file)
@@ -566,12 +566,12 @@ void setupLuaInspection()
       ret << endl;
 
       ret << "Frontends:" << endl;
-      fmt = boost::format("%-3d %-20.20s %-20d %-20d %-25d %-20d %-20d %-20d %-20f %-20f %-15d %-15d");
-      ret << (fmt % "#" % "Address" % "Connections" % "Died reading query" % "Died sending response" % "Gave up" % "Client timeouts" % "Downstream timeouts" % "Avg queries/conn" % "Avg duration" % "TLS new sessions" % "TLS Resumptions") << endl;
+      fmt = boost::format("%-3d %-20.20s %-20d %-20d %-25d %-20d %-20d %-20d %-20f %-20f %-15d %-15d %-15d %-15d %-15d %-15d %-15d");
+      ret << (fmt % "#" % "Address" % "Connections" % "Died reading query" % "Died sending response" % "Gave up" % "Client timeouts" % "Downstream timeouts" % "Avg queries/conn" % "Avg duration" % "TLS new sessions" % "TLS Resumptions" % "TLS 1.0" % "TLS 1.1" % "TLS 1.2" % "TLS 1.3" % "TLS other") << endl;
 
       size_t counter = 0;
       for(const auto& f : g_frontends) {
-        ret << (fmt % counter % f->local.toStringWithPort() % f->tcpCurrentConnections % f->tcpDiedReadingQuery % f->tcpDiedSendingResponse % f->tcpGaveUp % f->tcpClientTimeouts % f->tcpDownstreamTimeouts % f->tcpAvgQueriesPerConnection % f->tcpAvgConnectionDuration % f->tlsNewSessions % f->tlsResumptions) << endl;
+        ret << (fmt % counter % f->local.toStringWithPort() % f->tcpCurrentConnections % f->tcpDiedReadingQuery % f->tcpDiedSendingResponse % f->tcpGaveUp % f->tcpClientTimeouts % f->tcpDownstreamTimeouts % f->tcpAvgQueriesPerConnection % f->tcpAvgConnectionDuration % f->tlsNewSessions % f->tlsResumptions % f->tls10queries % f->tls11queries % f->tls12queries % f->tls13queries % f->tlsUnknownqueries) << endl;
         ++counter;
       }
       ret << endl;
index 04c08ca21c37789578e55e41cb3b8f5a0e501121..a20c2beec9d98eaaa8de97b01064abebc827c790 100644 (file)
@@ -1803,11 +1803,11 @@ void setupLuaConfig(bool client)
         setLuaNoSideEffect();
         try {
           ostringstream ret;
-          boost::format fmt("%-3d %-20.20s %-15d %-15d %-15d %-15d %-15d %-15d %-15d %-15d %-15d %-15d %-15d %-15d %-15d %-15d");
-          ret << (fmt % "#" % "Address" % "HTTP" % "HTTP/1" % "HTTP/2" % "TLS 1.0" % "TLS 1.1" % "TLS 1.2" % "TLS 1.3" % "TLS other" % "GET" % "POST" % "Bad" % "Errors" % "Redirects" % "Valid") << endl;
+          boost::format fmt("%-3d %-20.20s %-15d %-15d %-15d %-15d %-15d %-15d %-15d %-15d %-15d");
+          ret << (fmt % "#" % "Address" % "HTTP" % "HTTP/1" % "HTTP/2" % "GET" % "POST" % "Bad" % "Errors" % "Redirects" % "Valid") << endl;
           size_t counter = 0;
           for (const auto& ctx : g_dohlocals) {
-            ret << (fmt % counter % ctx->d_local.toStringWithPort() % ctx->d_httpconnects % ctx->d_http1Stats.d_nbQueries % ctx->d_http1Stats.d_nbQueries % ctx->d_tls10queries % ctx->d_tls11queries % ctx->d_tls12queries % ctx->d_tls13queries % ctx->d_tlsUnknownqueries % ctx->d_getqueries % ctx->d_postqueries % ctx->d_badrequests % ctx->d_errorresponses % ctx->d_redirectresponses % ctx->d_validresponses) << endl;
+            ret << (fmt % counter % ctx->d_local.toStringWithPort() % ctx->d_httpconnects % ctx->d_http1Stats.d_nbQueries % ctx->d_http1Stats.d_nbQueries % ctx->d_getqueries % ctx->d_postqueries % ctx->d_badrequests % ctx->d_errorresponses % ctx->d_redirectresponses % ctx->d_validresponses) << endl;
             counter++;
           }
           g_outputBuffer = ret.str();
index 403fbf601768370e17769bb603f07ae736c72a69..24e3184c5718e4dc748e8befbd14196f404e7505 100644 (file)
@@ -825,6 +825,26 @@ static void handleQuery(std::shared_ptr<IncomingTCPConnectionState>& state, stru
   ++state->d_ci.cs->queries;
   ++g_stats.queries;
 
+  if (state->d_handler.isTLS()) {
+    auto tlsVersion = state->d_handler.getTLSVersion();
+    switch (tlsVersion) {
+    case LibsslTLSVersion::TLS10:
+      ++state->d_ci.cs->tls10queries;
+      break;
+    case LibsslTLSVersion::TLS11:
+      ++state->d_ci.cs->tls11queries;
+      break;
+    case LibsslTLSVersion::TLS12:
+      ++state->d_ci.cs->tls12queries;
+      break;
+    case LibsslTLSVersion::TLS13:
+      ++state->d_ci.cs->tls13queries;
+      break;
+    default:
+      ++state->d_ci.cs->tlsUnknownqueries;
+    }
+  }
+
   /* we need an accurate ("real") value for the response and
      to store into the IDS, but not for insertion into the
      rings for example */
index 2f9b0096eadc2a430ddfaafe408659f4309c46a7..9033d14884c8963db4e1d77223c580330dd040cf 100644 (file)
@@ -556,6 +556,8 @@ static void connectionThread(int sock, ComboAddress remote)
         output << "# TYPE " << frontsbase << "tlsnewsessions " << "counter" << "\n";
         output << "# HELP " << frontsbase << "tlsresumptions " << "Amount of TLS sessions resumed" << "\n";
         output << "# TYPE " << frontsbase << "tlsresumptions " << "counter" << "\n";
+        output << "# HELP " << frontsbase << "tlsqueries " << "Number of queries received by dnsdist over TLS, by TLS version" << "\n";
+        output << "# TYPE " << frontsbase << "tlsqueries " << "counter" << "\n";
 
         std::map<std::string,uint64_t> frontendDuplicates;
         for (const auto& front : g_frontends) {
@@ -586,15 +588,18 @@ static void connectionThread(int sock, ComboAddress remote)
             output << frontsbase << "tcpavgconnectionduration" << label << front->tcpAvgConnectionDuration.load() << "\n";
             output << frontsbase << "tlsnewsessions" << label << front->tlsNewSessions.load() << "\n";
             output << frontsbase << "tlsresumptions" << label << front->tlsResumptions.load() << "\n";
+
+            output << frontsbase << "tlsqueries{frontend=\"" << frontName << "\",proto=\"" << proto << "\",tls=\"tls10\"} " << front->tls10queries.load() << "\n";
+            output << frontsbase << "tlsqueries{frontend=\"" << frontName << "\",proto=\"" << proto << "\",tls=\"tls11\"} " << front->tls11queries.load() << "\n";
+            output << frontsbase << "tlsqueries{frontend=\"" << frontName << "\",proto=\"" << proto << "\",tls=\"tls12\"} " << front->tls12queries.load() << "\n";
+            output << frontsbase << "tlsqueries{frontend=\"" << frontName << "\",proto=\"" << proto << "\",tls=\"tls13\"} " << front->tls13queries.load() << "\n";
+            output << frontsbase << "tlsqueries{frontend=\"" << frontName << "\",proto=\"" << proto << "\",tls=\"unknown\"} " << front->tlsUnknownqueries.load() << "\n";
           }
         }
 
         output << "# HELP " << frontsbase << "http_connects " << "Number of DoH TCP connections established to this frontend" << "\n";
         output << "# TYPE " << frontsbase << "http_connects " << "counter" << "\n";
 
-        output << "# HELP " << frontsbase << "doh_tls_queries " << "Number of DoH queries received by dnsdist, by TLS version" << "\n";
-        output << "# TYPE " << frontsbase << "doh_tls_queries " << "counter" << "\n";
-
         output << "# HELP " << frontsbase << "doh_http_method_queries " << "Number of DoH queries received by dnsdist, by HTTP method" << "\n";
         output << "# TYPE " << frontsbase << "doh_http_method_queries " << "counter" << "\n";
 
@@ -623,13 +628,6 @@ static void connectionThread(int sock, ComboAddress remote)
           const std::string label = "{" + addrlabel + "} ";
 
           output << frontsbase << "http_connects" << label << doh->d_httpconnects << "\n";
-
-          output << frontsbase << "doh_tls_queries{tls=\"tls10\"," << addrlabel << "} " << doh->d_tls10queries << "\n";
-          output << frontsbase << "doh_tls_queries{tls=\"tls11\"," << addrlabel << "} " << doh->d_tls11queries << "\n";
-          output << frontsbase << "doh_tls_queries{tls=\"tls12\"," << addrlabel << "} " << doh->d_tls12queries << "\n";
-          output << frontsbase << "doh_tls_queries{tls=\"tls13\"," << addrlabel << "} " << doh->d_tls13queries << "\n";
-          output << frontsbase << "doh_tls_queries{tls=\"unknown\"," << addrlabel << "} " << doh->d_tlsUnknownqueries << "\n";
-
           output << frontsbase << "doh_http_method_queries{method=\"get\"," << addrlabel << "} " << doh->d_getqueries << "\n";
           output << frontsbase << "doh_http_method_queries{method=\"post\"," << addrlabel << "} " << doh->d_postqueries << "\n";
 
@@ -799,11 +797,6 @@ static void connectionThread(int sock, ComboAddress remote)
             { "http2-502-responses", (double) doh->d_http2Stats.d_nb502Responses },
             { "http1-other-responses", (double) doh->d_http1Stats.d_nbOtherResponses },
             { "http2-other-responses", (double) doh->d_http2Stats.d_nbOtherResponses },
-            { "tls10-queries", (double) doh->d_tls10queries },
-            { "tls11-queries", (double) doh->d_tls11queries },
-            { "tls12-queries", (double) doh->d_tls12queries },
-            { "tls13-queries", (double) doh->d_tls13queries },
-            { "tls-unknown-queries", (double) doh->d_tlsUnknownqueries },
             { "get-queries", (double) doh->d_getqueries },
             { "post-queries", (double) doh->d_postqueries },
             { "bad-requests", (double) doh->d_badrequests },
index 81b32c37806c7d81527d00b2bf52b35dab50082d..b28cf44403f608aff3ee551267392d6107fc00d7 100644 (file)
@@ -685,6 +685,11 @@ struct ClientState
   std::atomic<uint64_t> tcpCurrentConnections{0};
   std::atomic<uint64_t> tlsNewSessions{0}; // A new TLS session has been negotiated, no resumption
   std::atomic<uint64_t> tlsResumptions{0}; // A TLS session has been resumed, either via session id or via a TLS ticket
+  std::atomic<uint64_t> tls10queries{0};   // valid DNS queries received via TLSv1.0
+  std::atomic<uint64_t> tls11queries{0};   // valid DNS queries received via TLSv1.1
+  std::atomic<uint64_t> tls12queries{0};   // valid DNS queries received via TLSv1.2
+  std::atomic<uint64_t> tls13queries{0};   // valid DNS queries received via TLSv1.3
+  std::atomic<uint64_t> tlsUnknownqueries{0};   // valid DNS queries received via unknown TLS version
 
   std::atomic<double> tcpAvgQueriesPerConnection{0.0};
   /* in ms */
index 6a065dee5ddaa3417165ad620be08847e51f823b..151c5d92e7b76a87149acbe7e118156c44d20833 100644 (file)
@@ -570,15 +570,15 @@ try
 
   if(auto tlsversion = h2o_socket_get_ssl_protocol_version(sock)) {
     if(!strcmp(tlsversion, "TLSv1.0"))
-      ++dsc->df->d_tls10queries;
+      ++dsc->cs->tls10queries;
     else if(!strcmp(tlsversion, "TLSv1.1"))
-      ++dsc->df->d_tls11queries;
+      ++dsc->cs->tls11queries;
     else if(!strcmp(tlsversion, "TLSv1.2"))
-      ++dsc->df->d_tls12queries;
+      ++dsc->cs->tls12queries;
     else if(!strcmp(tlsversion, "TLSv1.3"))
-      ++dsc->df->d_tls13queries;
+      ++dsc->cs->tls13queries;
     else
-      ++dsc->df->d_tlsUnknownqueries;
+      ++dsc->cs->tlsUnknownqueries;
   }
 
   string path(req->path.base, req->path.len);
index 4eaf0a924d57f68670333a7e5c9e931934dc734f..a3e09774fe5c963d78a3f121c2594d058cbc8f7a 100644 (file)
@@ -194,7 +194,7 @@ public:
     }
   }
 
-  std::string getServerNameIndication() override
+  std::string getServerNameIndication() const override
   {
     if (d_conn) {
       const char* value = SSL_get_servername(d_conn.get(), TLSEXT_NAMETYPE_host_name);
@@ -205,6 +205,25 @@ public:
     return std::string();
   }
 
+  LibsslTLSVersion getTLSVersion() const override
+  {
+    auto proto = SSL_version(d_conn.get());
+    switch (proto) {
+    case TLS1_VERSION:
+      return LibsslTLSVersion::TLS10;
+    case TLS1_1_VERSION:
+      return LibsslTLSVersion::TLS11;
+    case TLS1_2_VERSION:
+      return LibsslTLSVersion::TLS12;
+#ifdef TLS1_3_VERSION
+    case TLS1_3_VERSION:
+      return LibsslTLSVersion::TLS13;
+#endif /* TLS1_3_VERSION */
+    default:
+      return LibsslTLSVersion::Unknown;
+    }
+  }
+
   bool hasSessionBeenResumed() const override
   {
     if (d_conn) {
@@ -693,7 +712,7 @@ public:
     return got;
   }
 
-  std::string getServerNameIndication() override
+  std::string getServerNameIndication() const override
   {
     if (d_conn) {
       unsigned int type;
@@ -710,6 +729,25 @@ public:
     return std::string();
   }
 
+  LibsslTLSVersion getTLSVersion() const override
+  {
+    auto proto = gnutls_protocol_get_version(d_conn.get());
+    switch (proto) {
+    case GNUTLS_TLS1_0:
+      return LibsslTLSVersion::TLS10;
+    case GNUTLS_TLS1_1:
+      return LibsslTLSVersion::TLS11;
+    case GNUTLS_TLS1_2:
+      return LibsslTLSVersion::TLS12;
+#if GNUTLS_VERSION_NUMBER >= 0x030603
+    case GNUTLS_TLS1_3:
+      return LibsslTLSVersion::TLS13;
+#endif /* GNUTLS_VERSION_NUMBER >= 0x030603 */
+    default:
+      return LibsslTLSVersion::Unknown;
+    }
+  }
+
   bool hasSessionBeenResumed() const override
   {
     if (d_conn) {
index 41e6003293710bc4822b779896f7cca83631bc17..5ed812a5d8ba4dfdf14053c59310da14a2008e97 100644 (file)
@@ -65,19 +65,13 @@ struct DOHFrontend
   uint8_t d_numberOfTicketsKeys{5};
   bool d_enableTickets{true};
 
-  std::atomic<uint64_t> d_httpconnects;   // number of TCP/IP connections established
-  std::atomic<uint64_t> d_tls10queries;   // valid DNS queries received via TLSv1.0
-  std::atomic<uint64_t> d_tls11queries;   // valid DNS queries received via TLSv1.1
-  std::atomic<uint64_t> d_tls12queries;   // valid DNS queries received via TLSv1.2
-  std::atomic<uint64_t> d_tls13queries;   // valid DNS queries received via TLSv1.3
-  std::atomic<uint64_t> d_tlsUnknownqueries;   // valid DNS queries received via unknown TLS version
-
-  std::atomic<uint64_t> d_getqueries;     // valid DNS queries received via GET
-  std::atomic<uint64_t> d_postqueries;    // valid DNS queries received via POST
-  std::atomic<uint64_t> d_badrequests;     // request could not be converted to dns query
-  std::atomic<uint64_t> d_errorresponses; // dnsdist set 'error' on response
-  std::atomic<uint64_t> d_redirectresponses; // dnsdist set 'redirect' on response
-  std::atomic<uint64_t> d_validresponses; // valid responses sent out
+  std::atomic<uint64_t> d_httpconnects{0};   // number of TCP/IP connections established
+  std::atomic<uint64_t> d_getqueries{0};     // valid DNS queries received via GET
+  std::atomic<uint64_t> d_postqueries{0};    // valid DNS queries received via POST
+  std::atomic<uint64_t> d_badrequests{0};     // request could not be converted to dns query
+  std::atomic<uint64_t> d_errorresponses{0}; // dnsdist set 'error' on response
+  std::atomic<uint64_t> d_redirectresponses{0}; // dnsdist set 'redirect' on response
+  std::atomic<uint64_t> d_validresponses{0}; // valid responses sent out
 
   struct HTTPVersionStats
   {
index 895e09bbf65ae30e2e136593e71a209b926ad7f2..7fd52bcfb77ea916fefca2789e5d097bcfb0f802 100644 (file)
@@ -10,7 +10,7 @@
 #include "circular_buffer.hh"
 #include "lock.hh"
 
-enum class LibsslTLSVersion { TLS10, TLS11, TLS12, TLS13 };
+enum class LibsslTLSVersion { Unknown, TLS10, TLS11, TLS12, TLS13 };
 
 #ifdef HAVE_LIBSSL
 #include <openssl/ssl.h>
index 00daa2428001aded5d2e3fe728105694db139548..3f4df73e67a8766bb29fad793f6a99204c21ea71 100644 (file)
@@ -17,7 +17,8 @@ public:
   virtual size_t write(const void* buffer, size_t bufferSize, unsigned int writeTimeout) = 0;
   virtual IOState tryWrite(std::vector<uint8_t>& buffer, size_t& pos, size_t toWrite) = 0;
   virtual IOState tryRead(std::vector<uint8_t>& buffer, size_t& pos, size_t toRead) = 0;
-  virtual std::string getServerNameIndication() = 0;
+  virtual std::string getServerNameIndication() const = 0;
+  virtual LibsslTLSVersion getTLSVersion() const = 0;
   virtual bool hasSessionBeenResumed() const = 0;
   virtual void close() = 0;
 
@@ -280,7 +281,7 @@ public:
     }
   }
 
-  std::string getServerNameIndication()
+  std::string getServerNameIndication() const
   {
     if (d_conn) {
       return d_conn->getServerNameIndication();
@@ -288,6 +289,14 @@ public:
     return std::string();
   }
 
+  LibsslTLSVersion getTLSVersion() const
+  {
+    if (d_conn) {
+      return d_conn->getTLSVersion();
+    }
+    return LibsslTLSVersion::Unknown;
+  }
+
   bool isTLS() const
   {
     return d_conn != nullptr;