diff options
Diffstat (limited to 'doh.hh')
-rw-r--r-- | doh.hh | 271 |
1 files changed, 21 insertions, 250 deletions
@@ -21,266 +21,37 @@ */ #pragma once -#include <unordered_map> +#include "config.h" -#include "iputils.hh" -#include "libssl.hh" -#include "noinitvector.hh" -#include "stat_t.hh" +#ifdef HAVE_DNS_OVER_HTTPS +#ifdef HAVE_LIBH2OEVLOOP -struct DOHServerConfig; +#include <ctime> +#include <memory> +#include <string> -class DOHResponseMapEntry -{ -public: - DOHResponseMapEntry(const std::string& regex, uint16_t status, const PacketBuffer& content, const boost::optional<std::unordered_map<std::string, std::string>>& headers): d_regex(regex), d_customHeaders(headers), d_content(content), d_status(status) - { - if (status >= 400 && !d_content.empty() && d_content.at(d_content.size() -1) != 0) { - // we need to make sure it's null-terminated - d_content.push_back(0); - } - } - - bool matches(const std::string& path) const - { - return d_regex.match(path); - } - - uint16_t getStatusCode() const - { - return d_status; - } - - const PacketBuffer& getContent() const - { - return d_content; - } - - const boost::optional<std::unordered_map<std::string, std::string>>& getHeaders() const - { - return d_customHeaders; - } - -private: - Regex d_regex; - boost::optional<std::unordered_map<std::string, std::string>> d_customHeaders; - PacketBuffer d_content; - uint16_t d_status; -}; - -struct DOHFrontend -{ - DOHFrontend() - { - } - - std::shared_ptr<DOHServerConfig> d_dsc{nullptr}; - std::shared_ptr<std::vector<std::shared_ptr<DOHResponseMapEntry>>> d_responsesMap; - TLSConfig d_tlsConfig; - TLSErrorCounters d_tlsCounters; - std::string d_serverTokens{"h2o/dnsdist"}; - std::unordered_map<std::string, std::string> d_customResponseHeaders; - ComboAddress d_local; - - uint32_t d_idleTimeout{30}; // HTTP idle timeout in seconds - std::vector<std::string> d_urls; - - pdns::stat_t d_httpconnects{0}; // number of TCP/IP connections established - pdns::stat_t d_getqueries{0}; // valid DNS queries received via GET - pdns::stat_t d_postqueries{0}; // valid DNS queries received via POST - pdns::stat_t d_badrequests{0}; // request could not be converted to dns query - pdns::stat_t d_errorresponses{0}; // dnsdist set 'error' on response - pdns::stat_t d_redirectresponses{0}; // dnsdist set 'redirect' on response - pdns::stat_t d_validresponses{0}; // valid responses sent out - - struct HTTPVersionStats - { - pdns::stat_t d_nbQueries{0}; // valid DNS queries received - pdns::stat_t d_nb200Responses{0}; - pdns::stat_t d_nb400Responses{0}; - pdns::stat_t d_nb403Responses{0}; - pdns::stat_t d_nb500Responses{0}; - pdns::stat_t d_nb502Responses{0}; - pdns::stat_t d_nbOtherResponses{0}; - }; - - HTTPVersionStats d_http1Stats; - HTTPVersionStats d_http2Stats; -#ifdef __linux__ - // On Linux this gives us 128k pending queries (default is 8192 queries), - // which should be enough to deal with huge spikes - uint32_t d_internalPipeBufferSize{1024*1024}; -#else - uint32_t d_internalPipeBufferSize{0}; -#endif - bool d_sendCacheControlHeaders{true}; - bool d_trustForwardedForHeader{false}; - /* whether we require tue query path to exactly match one of configured ones, - or accept everything below these paths. */ - bool d_exactPathMatching{true}; - bool d_keepIncomingHeaders{false}; - - time_t getTicketsKeyRotationDelay() const - { - return d_tlsConfig.d_ticketsKeyRotationDelay; - } - - bool isHTTPS() const - { - return !d_tlsConfig.d_certKeyPairs.empty(); - } - -#ifndef HAVE_DNS_OVER_HTTPS - void setup() - { - } - - void reloadCertificates() - { - } - - void rotateTicketsKey(time_t /* now */) - { - } - - void loadTicketsKeys(const std::string& /* keyFile */) - { - } - - void handleTicketsKeyRotation() - { - } - - time_t getNextTicketsKeyRotation() const - { - return 0; - } - - size_t getTicketsKeysCount() const - { - size_t res = 0; - return res; - } - -#else - void setup(); - void reloadCertificates(); - - void rotateTicketsKey(time_t now); - void loadTicketsKeys(const std::string& keyFile); - void handleTicketsKeyRotation(); - time_t getNextTicketsKeyRotation() const; - size_t getTicketsKeysCount() const; -#endif /* HAVE_DNS_OVER_HTTPS */ -}; - -#ifndef HAVE_DNS_OVER_HTTPS -struct DOHUnit -{ - static void release(DOHUnit*) - { - } - - void get() - { - } - - void release() - { - } - - size_t proxyProtocolPayloadSize{0}; - uint16_t status_code{200}; -}; - -#else /* HAVE_DNS_OVER_HTTPS */ -#include <unordered_map> +struct CrossProtocolQuery; +struct DNSQuestion; -#include "dnsdist-idstate.hh" +std::unique_ptr<CrossProtocolQuery> getDoHCrossProtocolQueryFromDQ(DNSQuestion& dq, bool isResponse); -struct st_h2o_req_t; -struct DownstreamState; +#include "dnsdist-doh-common.hh" -struct DOHUnit +struct H2ODOHFrontend : public DOHFrontend { - DOHUnit(PacketBuffer&& q, std::string&& p, std::string&& h): path(std::move(p)), host(std::move(h)), query(std::move(q)) - { - ids.ednsAdded = false; - } - - DOHUnit(const DOHUnit&) = delete; - DOHUnit& operator=(const DOHUnit&) = delete; - - void get() - { - ++d_refcnt; - } - - void release() - { - if (--d_refcnt == 0) { - if (self) { - *self = nullptr; - } - - delete this; - } - } - - static void release(DOHUnit* ptr) - { - if (ptr) { - ptr->release(); - } - } +public: - InternalQueryState ids; - std::string sni; - std::string path; - std::string scheme; - std::string host; - std::string contentType; - PacketBuffer query; - PacketBuffer response; - std::shared_ptr<DownstreamState> downstream{nullptr}; - std::unique_ptr<std::unordered_map<std::string, std::string>> headers; - st_h2o_req_t* req{nullptr}; - DOHUnit** self{nullptr}; - DOHServerConfig* dsc{nullptr}; - std::atomic<uint64_t> d_refcnt{1}; - size_t query_at{0}; - size_t proxyProtocolPayloadSize{0}; - int rsock{-1}; - /* the status_code is set from - processDOHQuery() (which is executed in - the DOH client thread) so that the correct - response can be sent in on_dnsdist(), - after the DOHUnit has been passed back to - the main DoH thread. - */ - uint16_t status_code{200}; - /* whether the query was re-sent to the backend over - TCP after receiving a truncated answer over UDP */ - bool tcp{false}; - bool truncated{false}; + void setup() override; + void reloadCertificates() override; - std::string getHTTPPath() const; - std::string getHTTPHost() const; - std::string getHTTPScheme() const; - std::string getHTTPQueryString() const; - std::unordered_map<std::string, std::string> getHTTPHeaders() const; - void setHTTPResponse(uint16_t statusCode, PacketBuffer&& body, const std::string& contentType=""); + void rotateTicketsKey(time_t now) override; + void loadTicketsKeys(const std::string& keyFile) override; + void handleTicketsKeyRotation() override; + std::string getNextTicketsKeyRotation() const override; + size_t getTicketsKeysCount() override; }; -void handleUDPResponseForDoH(std::unique_ptr<DOHUnit, void(*)(DOHUnit*)>&&, PacketBuffer&& response, InternalQueryState&& state); - -struct CrossProtocolQuery; -struct DNSQuestion; - -std::unique_ptr<CrossProtocolQuery> getDoHCrossProtocolQueryFromDQ(DNSQuestion& dq, bool isResponse); +void dohThread(ClientState* clientState); +#endif /* HAVE_LIBH2OEVLOOP */ #endif /* HAVE_DNS_OVER_HTTPS */ - -using DOHUnitUniquePtr = std::unique_ptr<DOHUnit, void(*)(DOHUnit*)>; - -void handleDOHTimeout(DOHUnitUniquePtr&& oldDU); |