summaryrefslogtreecommitdiffstats
path: root/doh.hh
diff options
context:
space:
mode:
Diffstat (limited to 'doh.hh')
-rw-r--r--doh.hh271
1 files changed, 21 insertions, 250 deletions
diff --git a/doh.hh b/doh.hh
index 96e65f1..58a26f1 100644
--- a/doh.hh
+++ b/doh.hh
@@ -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);