Skip to content

Commit

Permalink
dnsdist: Add DoH3 headers, query string, path and scheme bindings
Browse files Browse the repository at this point in the history
The DoH ones have been there for a long time, but the DoH3 ones were
missing. Note that we still don't have the ability to set a HTTP
response for DoH3 queries (including response maps) and SNI is still
missing (Quiche does not make that last one easy).
  • Loading branch information
rgacogne committed Dec 30, 2024
1 parent 788f396 commit 4541c12
Show file tree
Hide file tree
Showing 10 changed files with 393 additions and 87 deletions.
3 changes: 3 additions & 0 deletions pdns/dnsdistdist/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -480,12 +480,15 @@ endif

if HAVE_DNS_OVER_HTTP3
dnsdist_SOURCES += doh3.cc
testrunner_SOURCES += doh3.cc
endif

if HAVE_QUICHE
AM_CPPFLAGS += $(QUICHE_CFLAGS)
dnsdist_LDADD += $(QUICHE_LDFLAGS) $(QUICHE_LIBS)
dnsdist_SOURCES += doq-common.cc
testrunner_SOURCES += doq-common.cc
testrunner_LDADD += $(QUICHE_LDFLAGS) $(QUICHE_LIBS)
endif

if !HAVE_LUA_HPP
Expand Down
43 changes: 28 additions & 15 deletions pdns/dnsdistdist/dnsdist-doh-common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,23 @@ HTTPHeaderRule::HTTPHeaderRule(const std::string& header, const std::string& reg

bool HTTPHeaderRule::matches(const DNSQuestion* dq) const
{
if (!dq->ids.du) {
if (dq->ids.du) {
const auto& headers = dq->ids.du->getHTTPHeaders();
for (const auto& header : headers) {
if (header.first == d_header) {
return d_regex.match(header.second);
}
}
return false;
}

const auto& headers = dq->ids.du->getHTTPHeaders();
for (const auto& header : headers) {
if (header.first == d_header) {
return d_regex.match(header.second);
if (dq->ids.doh3u) {
const auto& headers = dq->ids.doh3u->getHTTPHeaders();
for (const auto& header : headers) {
if (header.first == d_header) {
return d_regex.match(header.second);
}
}
return false;
}
return false;
}
Expand All @@ -57,12 +65,14 @@ HTTPPathRule::HTTPPathRule(std::string path) :

bool HTTPPathRule::matches(const DNSQuestion* dq) const
{
if (!dq->ids.du) {
return false;
if (dq->ids.du) {
const auto path = dq->ids.du->getHTTPPath();
return d_path == path;
}

const auto path = dq->ids.du->getHTTPPath();
return d_path == path;
else if (dq->ids.doh3u) {

Check warning on line 72 in pdns/dnsdistdist/dnsdist-doh-common.cc

View workflow job for this annotation

GitHub Actions / Analyze (cpp, dnsdist)

do not use 'else' after 'return' (readability-else-after-return - Level=Warning)
return dq->ids.doh3u->getHTTPPath() == d_path;
}
return false;
}

string HTTPPathRule::toString() const
Expand All @@ -77,11 +87,14 @@ HTTPPathRegexRule::HTTPPathRegexRule(const std::string& regex) :

bool HTTPPathRegexRule::matches(const DNSQuestion* dq) const
{
if (!dq->ids.du) {
return false;
if (dq->ids.du) {
const auto path = dq->ids.du->getHTTPPath();
return d_regex.match(path);
}

return d_regex.match(dq->ids.du->getHTTPPath());
else if (dq->ids.doh3u) {

Check warning on line 94 in pdns/dnsdistdist/dnsdist-doh-common.cc

View workflow job for this annotation

GitHub Actions / Analyze (cpp, dnsdist)

do not use 'else' after 'return' (readability-else-after-return - Level=Warning)
return d_regex.match(dq->ids.doh3u->getHTTPPath());
}
return false;
}

string HTTPPathRegexRule::toString() const
Expand Down
46 changes: 31 additions & 15 deletions pdns/dnsdistdist/dnsdist-lua-bindings-dnsquestion.cc
Original file line number Diff line number Diff line change
Expand Up @@ -513,38 +513,54 @@ void setupLuaBindingsDNSQuestion(LuaContext& luaCtx)

#ifdef HAVE_DNS_OVER_HTTPS
luaCtx.registerFunction<std::string (DNSQuestion::*)(void) const>("getHTTPPath", [](const DNSQuestion& dnsQuestion) {
if (dnsQuestion.ids.du == nullptr) {
return std::string();
if (dnsQuestion.ids.du) {
return dnsQuestion.ids.du->getHTTPPath();
}
if (dnsQuestion.ids.doh3u) {
return dnsQuestion.ids.doh3u->getHTTPPath();
}
return dnsQuestion.ids.du->getHTTPPath();
return std::string();

});

luaCtx.registerFunction<std::string (DNSQuestion::*)(void) const>("getHTTPQueryString", [](const DNSQuestion& dnsQuestion) {
if (dnsQuestion.ids.du == nullptr) {
return std::string();
if (dnsQuestion.ids.du) {
return dnsQuestion.ids.du->getHTTPQueryString();
}
if (dnsQuestion.ids.doh3u) {
return dnsQuestion.ids.doh3u->getHTTPQueryString();
}
return dnsQuestion.ids.du->getHTTPQueryString();
return std::string();
});

luaCtx.registerFunction<std::string (DNSQuestion::*)(void) const>("getHTTPHost", [](const DNSQuestion& dnsQuestion) {
if (dnsQuestion.ids.du == nullptr) {
return std::string();
if (dnsQuestion.ids.du) {
return dnsQuestion.ids.du->getHTTPHost();
}
return dnsQuestion.ids.du->getHTTPHost();
if (dnsQuestion.ids.doh3u) {
return dnsQuestion.ids.doh3u->getHTTPHost();
}
return std::string();
});

luaCtx.registerFunction<std::string (DNSQuestion::*)(void) const>("getHTTPScheme", [](const DNSQuestion& dnsQuestion) {
if (dnsQuestion.ids.du == nullptr) {
return std::string();
if (dnsQuestion.ids.du) {
return dnsQuestion.ids.du->getHTTPScheme();
}
if (dnsQuestion.ids.doh3u) {
return dnsQuestion.ids.doh3u->getHTTPScheme();
}
return dnsQuestion.ids.du->getHTTPScheme();
return std::string();
});

luaCtx.registerFunction<LuaAssociativeTable<std::string> (DNSQuestion::*)(void) const>("getHTTPHeaders", [](const DNSQuestion& dnsQuestion) {
if (dnsQuestion.ids.du == nullptr) {
return LuaAssociativeTable<std::string>();
if (dnsQuestion.ids.du) {
return dnsQuestion.ids.du->getHTTPHeaders();
}
if (dnsQuestion.ids.doh3u) {
return dnsQuestion.ids.doh3u->getHTTPHeaders();
}
return dnsQuestion.ids.du->getHTTPHeaders();
return LuaAssociativeTable<std::string>();
});

luaCtx.registerFunction<void (DNSQuestion::*)(uint64_t statusCode, const std::string& body, const boost::optional<std::string> contentType)>("setHTTPResponse", [](DNSQuestion& dnsQuestion, uint64_t statusCode, const std::string& body, const boost::optional<std::string>& contentType) {
Expand Down
101 changes: 63 additions & 38 deletions pdns/dnsdistdist/dnsdist-lua-ffi.cc
Original file line number Diff line number Diff line change
Expand Up @@ -294,12 +294,16 @@ size_t dnsdist_ffi_dnsquestion_get_tag_raw(const dnsdist_ffi_dnsquestion_t* dq,
const char* dnsdist_ffi_dnsquestion_get_http_path(dnsdist_ffi_dnsquestion_t* dq)
{
if (!dq->httpPath) {
if (dq->dq->ids.du == nullptr) {
return nullptr;
}
#ifdef HAVE_DNS_OVER_HTTPS
dq->httpPath = dq->dq->ids.du->getHTTPPath();
if (dq->dq->ids.du) {
#if defined(HAVE_DNS_OVER_HTTPS)
dq->httpPath = dq->dq->ids.du->getHTTPPath();
#endif /* HAVE_DNS_OVER_HTTPS */
}
else if (dq->dq->ids.doh3u) {
#if defined(HAVE_DNS_OVER_HTTP3)
dq->httpPath = dq->dq->ids.doh3u->getHTTPPath();
#endif /* HAVE_DNS_OVER_HTTP3 */
}
}
if (dq->httpPath) {
return dq->httpPath->c_str();
Expand All @@ -310,12 +314,16 @@ const char* dnsdist_ffi_dnsquestion_get_http_path(dnsdist_ffi_dnsquestion_t* dq)
const char* dnsdist_ffi_dnsquestion_get_http_query_string(dnsdist_ffi_dnsquestion_t* dq)
{
if (!dq->httpQueryString) {
if (dq->dq->ids.du == nullptr) {
return nullptr;
}
if (dq->dq->ids.du) {
#ifdef HAVE_DNS_OVER_HTTPS
dq->httpQueryString = dq->dq->ids.du->getHTTPQueryString();
dq->httpQueryString = dq->dq->ids.du->getHTTPQueryString();
#endif /* HAVE_DNS_OVER_HTTPS */
}
else if (dq->dq->ids.doh3u) {
#if defined(HAVE_DNS_OVER_HTTP3)
dq->httpQueryString = dq->dq->ids.doh3u->getHTTPQueryString();
#endif /* HAVE_DNS_OVER_HTTP3 */
}
}
if (dq->httpQueryString) {
return dq->httpQueryString->c_str();
Expand All @@ -326,12 +334,16 @@ const char* dnsdist_ffi_dnsquestion_get_http_query_string(dnsdist_ffi_dnsquestio
const char* dnsdist_ffi_dnsquestion_get_http_host(dnsdist_ffi_dnsquestion_t* dq)
{
if (!dq->httpHost) {
if (dq->dq->ids.du == nullptr) {
return nullptr;
}
if (dq->dq->ids.du) {
#ifdef HAVE_DNS_OVER_HTTPS
dq->httpHost = dq->dq->ids.du->getHTTPHost();
dq->httpHost = dq->dq->ids.du->getHTTPHost();
#endif /* HAVE_DNS_OVER_HTTPS */
}
else if (dq->dq->ids.doh3u) {
#if defined(HAVE_DNS_OVER_HTTP3)
dq->httpHost = dq->dq->ids.doh3u->getHTTPHost();
#endif /* HAVE_DNS_OVER_HTTP3 */
}
}
if (dq->httpHost) {
return dq->httpHost->c_str();
Expand All @@ -342,12 +354,16 @@ const char* dnsdist_ffi_dnsquestion_get_http_host(dnsdist_ffi_dnsquestion_t* dq)
const char* dnsdist_ffi_dnsquestion_get_http_scheme(dnsdist_ffi_dnsquestion_t* dq)
{
if (!dq->httpScheme) {
if (dq->dq->ids.du == nullptr) {
return nullptr;
}
if (dq->dq->ids.du) {
#ifdef HAVE_DNS_OVER_HTTPS
dq->httpScheme = dq->dq->ids.du->getHTTPScheme();
dq->httpScheme = dq->dq->ids.du->getHTTPScheme();
#endif /* HAVE_DNS_OVER_HTTPS */
}
else if (dq->dq->ids.doh3u) {
#if defined(HAVE_DNS_OVER_HTTP3)
dq->httpScheme = dq->dq->ids.doh3u->getHTTPScheme();
#endif /* HAVE_DNS_OVER_HTTP3 */
}
}
if (dq->httpScheme) {
return dq->httpScheme->c_str();
Expand Down Expand Up @@ -404,36 +420,45 @@ size_t dnsdist_ffi_dnsquestion_get_edns_options(dnsdist_ffi_dnsquestion_t* dq, c

size_t dnsdist_ffi_dnsquestion_get_http_headers(dnsdist_ffi_dnsquestion_t* dq, const dnsdist_ffi_http_header_t** out)
{
if (dq->dq->ids.du == nullptr) {
return 0;
}
#if defined(HAVE_DNS_OVER_HTTPS) || defined(HAVE_DNS_OVER_HTTP3)
const auto processHeaders = [&dq](const std::unordered_map<std::string, std::string>& headers) {
if (headers.size() == 0) {

Check warning on line 425 in pdns/dnsdistdist/dnsdist-lua-ffi.cc

View workflow job for this annotation

GitHub Actions / Analyze (cpp, dnsdist)

the 'empty' method should be used to check for emptiness instead of 'size' (readability-container-size-empty - Level=Warning)
return;
}
dq->httpHeaders = std::make_unique<std::unordered_map<std::string, std::string>>(std::move(headers));

Check warning on line 428 in pdns/dnsdistdist/dnsdist-lua-ffi.cc

View workflow job for this annotation

GitHub Actions / Analyze (cpp, dnsdist)

std::move of the const variable 'headers' has no effect; remove std::move() or make the variable non-const (performance-move-const-arg - Level=Warning)
if (!dq->httpHeadersVect) {
dq->httpHeadersVect = std::make_unique<std::vector<dnsdist_ffi_http_header_t>>();
}
dq->httpHeadersVect->clear();
dq->httpHeadersVect->resize(dq->httpHeaders->size());
size_t pos = 0;
for (const auto& header : *dq->httpHeaders) {
dq->httpHeadersVect->at(pos).name = header.first.c_str();
dq->httpHeadersVect->at(pos).value = header.second.c_str();
++pos;
}
};

#ifdef HAVE_DNS_OVER_HTTPS
auto headers = dq->dq->ids.du->getHTTPHeaders();
if (headers.size() == 0) {
return 0;
#if defined(HAVE_DNS_OVER_HTTPS)
if (dq->dq->ids.du) {
const auto& headers = dq->dq->ids.du->getHTTPHeaders();
processHeaders(headers);
}
dq->httpHeaders = std::make_unique<std::unordered_map<std::string, std::string>>(std::move(headers));
if (!dq->httpHeadersVect) {
dq->httpHeadersVect = std::make_unique<std::vector<dnsdist_ffi_http_header_t>>();
}
dq->httpHeadersVect->clear();
dq->httpHeadersVect->resize(dq->httpHeaders->size());
size_t pos = 0;
for (const auto& header : *dq->httpHeaders) {
dq->httpHeadersVect->at(pos).name = header.first.c_str();
dq->httpHeadersVect->at(pos).value = header.second.c_str();
++pos;
#endif /* HAVE_DNS_OVER_HTTPS */
#if defined(HAVE_DNS_OVER_HTTP3)
if (dq->dq->ids.doh3u) {
const auto& headers = dq->dq->ids.doh3u->getHTTPHeaders();
processHeaders(headers);
}
#endif /* HAVE_DNS_OVER_HTTP3 */

if (!dq->httpHeadersVect->empty()) {
*out = dq->httpHeadersVect->data();
}

return dq->httpHeadersVect->size();
#else
#else /* HAVE_DNS_OVER_HTTPS || HAVE_DNS_OVER_HTTP3 */
return 0;
#endif
#endif /* HAVE_DNS_OVER_HTTPS || HAVE_DNS_OVER_HTTP3 */
}

size_t dnsdist_ffi_dnsquestion_get_tag_array(dnsdist_ffi_dnsquestion_t* dq, const dnsdist_ffi_tag_t** out)
Expand Down
Loading

0 comments on commit 4541c12

Please sign in to comment.