From: Remi Gacogne Date: Mon, 7 Oct 2019 14:00:59 +0000 (+0200) Subject: dnsdist: Add metrics about TLS versions with DNS over TLS X-Git-Tag: dnsdist-1.4.0-rc4~33^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bb3954f081a6790be496ac2651fa52210afb9268;p=thirdparty%2Fpdns.git dnsdist: Add metrics about TLS versions with DNS over TLS --- diff --git a/pdns/dnsdist-carbon.cc b/pdns/dnsdist-carbon.cc index 41fc44f64d..755832815b 100644 --- a/pdns/dnsdist-carbon.cc +++ b/pdns/dnsdist-carbon.cc @@ -132,6 +132,11 @@ try str<tcpAvgConnectionDuration.load() << " " << now << "\r\n"; str<tlsNewSessions.load() << " " << now << "\r\n"; str<tlsResumptions.load() << " " << now << "\r\n"; + str<tls10queries.load() << " " << now << "\r\n"; + str<tls11queries.load() << " " << now << "\r\n"; + str<tls12queries.load() << " " << now << "\r\n"; + str<tls13queries.load() << " " << now << "\r\n"; + str<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}, diff --git a/pdns/dnsdist-lua-inspection.cc b/pdns/dnsdist-lua-inspection.cc index 1a3cd227f1..ebad23400b 100644 --- a/pdns/dnsdist-lua-inspection.cc +++ b/pdns/dnsdist-lua-inspection.cc @@ -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; diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index 04c08ca21c..a20c2beec9 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -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(); diff --git a/pdns/dnsdist-tcp.cc b/pdns/dnsdist-tcp.cc index 403fbf6017..24e3184c57 100644 --- a/pdns/dnsdist-tcp.cc +++ b/pdns/dnsdist-tcp.cc @@ -825,6 +825,26 @@ static void handleQuery(std::shared_ptr& 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 */ diff --git a/pdns/dnsdist-web.cc b/pdns/dnsdist-web.cc index 2f9b0096ea..9033d14884 100644 --- a/pdns/dnsdist-web.cc +++ b/pdns/dnsdist-web.cc @@ -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 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 }, diff --git a/pdns/dnsdist.hh b/pdns/dnsdist.hh index 81b32c3780..b28cf44403 100644 --- a/pdns/dnsdist.hh +++ b/pdns/dnsdist.hh @@ -685,6 +685,11 @@ struct ClientState std::atomic tcpCurrentConnections{0}; std::atomic tlsNewSessions{0}; // A new TLS session has been negotiated, no resumption std::atomic tlsResumptions{0}; // A TLS session has been resumed, either via session id or via a TLS ticket + std::atomic tls10queries{0}; // valid DNS queries received via TLSv1.0 + std::atomic tls11queries{0}; // valid DNS queries received via TLSv1.1 + std::atomic tls12queries{0}; // valid DNS queries received via TLSv1.2 + std::atomic tls13queries{0}; // valid DNS queries received via TLSv1.3 + std::atomic tlsUnknownqueries{0}; // valid DNS queries received via unknown TLS version std::atomic tcpAvgQueriesPerConnection{0.0}; /* in ms */ diff --git a/pdns/dnsdistdist/doh.cc b/pdns/dnsdistdist/doh.cc index 6a065dee5d..151c5d92e7 100644 --- a/pdns/dnsdistdist/doh.cc +++ b/pdns/dnsdistdist/doh.cc @@ -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); diff --git a/pdns/dnsdistdist/tcpiohandler.cc b/pdns/dnsdistdist/tcpiohandler.cc index 4eaf0a924d..a3e09774fe 100644 --- a/pdns/dnsdistdist/tcpiohandler.cc +++ b/pdns/dnsdistdist/tcpiohandler.cc @@ -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) { diff --git a/pdns/doh.hh b/pdns/doh.hh index 41e6003293..5ed812a5d8 100644 --- a/pdns/doh.hh +++ b/pdns/doh.hh @@ -65,19 +65,13 @@ struct DOHFrontend uint8_t d_numberOfTicketsKeys{5}; bool d_enableTickets{true}; - std::atomic d_httpconnects; // number of TCP/IP connections established - std::atomic d_tls10queries; // valid DNS queries received via TLSv1.0 - std::atomic d_tls11queries; // valid DNS queries received via TLSv1.1 - std::atomic d_tls12queries; // valid DNS queries received via TLSv1.2 - std::atomic d_tls13queries; // valid DNS queries received via TLSv1.3 - std::atomic d_tlsUnknownqueries; // valid DNS queries received via unknown TLS version - - std::atomic d_getqueries; // valid DNS queries received via GET - std::atomic d_postqueries; // valid DNS queries received via POST - std::atomic d_badrequests; // request could not be converted to dns query - std::atomic d_errorresponses; // dnsdist set 'error' on response - std::atomic d_redirectresponses; // dnsdist set 'redirect' on response - std::atomic d_validresponses; // valid responses sent out + std::atomic d_httpconnects{0}; // number of TCP/IP connections established + std::atomic d_getqueries{0}; // valid DNS queries received via GET + std::atomic d_postqueries{0}; // valid DNS queries received via POST + std::atomic d_badrequests{0}; // request could not be converted to dns query + std::atomic d_errorresponses{0}; // dnsdist set 'error' on response + std::atomic d_redirectresponses{0}; // dnsdist set 'redirect' on response + std::atomic d_validresponses{0}; // valid responses sent out struct HTTPVersionStats { diff --git a/pdns/libssl.hh b/pdns/libssl.hh index 895e09bbf6..7fd52bcfb7 100644 --- a/pdns/libssl.hh +++ b/pdns/libssl.hh @@ -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 diff --git a/pdns/tcpiohandler.hh b/pdns/tcpiohandler.hh index 00daa24280..3f4df73e67 100644 --- a/pdns/tcpiohandler.hh +++ b/pdns/tcpiohandler.hh @@ -17,7 +17,8 @@ public: virtual size_t write(const void* buffer, size_t bufferSize, unsigned int writeTimeout) = 0; virtual IOState tryWrite(std::vector& buffer, size_t& pos, size_t toWrite) = 0; virtual IOState tryRead(std::vector& 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;