From: Remi Gacogne Date: Wed, 25 Aug 2021 14:14:46 +0000 (+0200) Subject: dnsdist: Add initial support for TCP/DoT -> DoH X-Git-Tag: dnsdist-1.7.0-alpha1~23^2~27 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=89e62bd841a9c3cfa7cabef957e8e04110367531;p=thirdparty%2Fpdns.git dnsdist: Add initial support for TCP/DoT -> DoH --- diff --git a/pdns/dnsdist-tcp.cc b/pdns/dnsdist-tcp.cc index 2ca6320c7f..2752ea8bf2 100644 --- a/pdns/dnsdist-tcp.cc +++ b/pdns/dnsdist-tcp.cc @@ -412,19 +412,22 @@ void IncomingTCPConnectionState::handleResponse(const struct timeval& now, TCPRe if (response.d_connection && response.d_connection->isIdle()) { // if we have added a TCP Proxy Protocol payload to a connection, don't release it to the general pool yet, no one else will be able to use it anyway if (response.d_connection->canBeReused()) { - auto& list = state->d_activeConnectionsToBackend.at(response.d_connection->getDS()); - - for (auto it = list.begin(); it != list.end(); ++it) { - if (*it == response.d_connection) { - try { - response.d_connection->release(); - DownstreamConnectionsManager::releaseDownstreamConnection(std::move(*it)); - } - catch (const std::exception& e) { - vinfolog("Error releasing connection: %s", e.what()); + const auto connIt = state->d_activeConnectionsToBackend.find(response.d_connection->getDS()); + if (connIt != state->d_activeConnectionsToBackend.end()) { + auto& list = connIt->second; + + for (auto it = list.begin(); it != list.end(); ++it) { + if (*it == response.d_connection) { + try { + response.d_connection->release(); + DownstreamConnectionsManager::releaseDownstreamConnection(std::move(*it)); + } + catch (const std::exception& e) { + vinfolog("Error releasing connection: %s", e.what()); + } + list.erase(it); + break; } - list.erase(it); - break; } } } @@ -468,6 +471,30 @@ void IncomingTCPConnectionState::handleResponse(const struct timeval& now, TCPRe queueResponse(state, now, std::move(response)); } +class TCPCrossProtocolQuery : public CrossProtocolQuery +{ +public: + TCPCrossProtocolQuery(PacketBuffer&& buffer, IDState&& ids, std::shared_ptr& ds, std::shared_ptr& sender): d_sender(sender) + { + query = InternalQuery(std::move(buffer), std::move(ids)); + downstream = ds; + #warning handle proxy protocol payload + proxyProtocolPayloadSize = 0; + } + + ~TCPCrossProtocolQuery() + { + } + + std::shared_ptr getTCPQuerySender() override + { + return d_sender; + } + +private: + std::shared_ptr d_sender; +}; + static void handleQuery(std::shared_ptr& state, const struct timeval& now) { if (state->d_querySize < sizeof(dnsheader)) { @@ -590,6 +617,16 @@ static void handleQuery(std::shared_ptr& state, cons setIDStateFromDNSQuestion(ids, dq, std::move(qname)); ids.origID = dh->id; + ++state->d_currentQueriesCount; + + if (ds->isDoH()) { + std::shared_ptr incoming = state; + auto cpq = std::make_unique(std::move(state->d_buffer), std::move(ids), ds, state); + + ds->passCrossProtocolQuery(std::move(cpq)); + return; + } + prependSizeToTCPQuery(state->d_buffer, 0); #warning FIXME: handle DoH backends here @@ -624,7 +661,6 @@ static void handleQuery(std::shared_ptr& state, cons query.d_proxyProtocolPayload = std::move(proxyProtocolPayload); } - ++state->d_currentQueriesCount; vinfolog("Got query for %s|%s from %s (%s, %d bytes), relayed to %s", query.d_idstate.qname.toLogString(), QType(query.d_idstate.qtype).toString(), state->d_proxiedRemote.toStringWithPort(), (state->d_handler.isTLS() ? "DoT" : "TCP"), query.d_buffer.size(), ds->getName()); std::shared_ptr incoming = state; downstreamConnection->queueQuery(incoming, std::move(query)); diff --git a/pdns/dnsdistdist/dnsdist-nghttp2.cc b/pdns/dnsdistdist/dnsdist-nghttp2.cc index 8c56f9d8c6..1f79a6269e 100644 --- a/pdns/dnsdistdist/dnsdist-nghttp2.cc +++ b/pdns/dnsdistdist/dnsdist-nghttp2.cc @@ -284,7 +284,6 @@ void DoHConnectionToBackend::handleReadableIOCallback(int fd, FDMultiplexer::fun //cerr<<"trying to read "<d_in.size()<d_handler->tryRead(conn->d_in, conn->d_inPos, conn->d_in.size(), true); - // userData.d_handler->tryRead(userData.d_in, pos, userData.d_in.size()); //cerr<<"got a "<<(int)newState<<" state and "<d_inPos<<" bytes"<d_in.resize(conn->d_inPos); if (newState == IOState::Done) { @@ -297,6 +296,11 @@ void DoHConnectionToBackend::handleReadableIOCallback(int fd, FDMultiplexer::fun return; } nghttp2_session_send(conn->d_session.get()); + if (conn->getConcurrentStreamsCount() == 0) { + conn->stopIO(); + ioGuard.release(); + break; + } } else { if (newState == IOState::NeedWrite) { @@ -453,7 +457,6 @@ int DoHConnectionToBackend::on_frame_recv_callback(nghttp2_session* session, con case NGHTTP2_DATA: cerr<<"got data"<