Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dnsdist: properly set protocol when logging #13716

Merged
merged 7 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,057 changes: 550 additions & 507 deletions pdns/dnsdist-lua-actions.cc

Large diffs are not rendered by default.

10 changes: 7 additions & 3 deletions pdns/dnsdist-lua.hh
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ struct ResponseConfig
boost::optional<bool> setRA{boost::none};
uint32_t ttl{60};
};
void setResponseHeadersFromConfig(dnsheader& dh, const ResponseConfig& config);
void setResponseHeadersFromConfig(dnsheader& dnsheader, const ResponseConfig& config);

class SpoofAction : public DNSAction
{
Expand Down Expand Up @@ -66,7 +66,7 @@ public:
{
}

DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override;
DNSAction::Action operator()(DNSQuestion* dnsquestion, string* ruleresult) const override;

string toString() const override
{
Expand All @@ -84,9 +84,13 @@ public:
return ret;
}

[[nodiscard]] ResponseConfig& getResponseConfig()
{
return d_responseConfig;
}

ResponseConfig d_responseConfig;
private:
ResponseConfig d_responseConfig;
static thread_local std::default_random_engine t_randomEngine;
std::vector<ComboAddress> d_addrs;
std::unordered_set<uint16_t> d_types;
Expand Down
83 changes: 43 additions & 40 deletions pdns/dnsdist-protobuf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@
#include "dnsdist-protobuf.hh"
#include "protozero.hh"

DNSDistProtoBufMessage::DNSDistProtoBufMessage(const DNSQuestion& dq) :
d_dq(dq), d_type(pdns::ProtoZero::Message::MessageType::DNSQueryType)
DNSDistProtoBufMessage::DNSDistProtoBufMessage(const DNSQuestion& dnsquestion) :
d_dq(dnsquestion)
{
}

DNSDistProtoBufMessage::DNSDistProtoBufMessage(const DNSResponse& dr, bool includeCNAME) :
d_dq(dr), d_dr(&dr), d_type(pdns::ProtoZero::Message::MessageType::DNSResponseType), d_includeCNAME(includeCNAME)
DNSDistProtoBufMessage::DNSDistProtoBufMessage(const DNSResponse& dnsresponse, bool includeCNAME) :
d_dq(dnsresponse), d_dr(&dnsresponse), d_type(pdns::ProtoZero::Message::MessageType::DNSResponseType), d_includeCNAME(includeCNAME)
{
}

Expand Down Expand Up @@ -268,14 +268,14 @@ ProtoBufMetaKey::ProtoBufMetaKey(const std::string& key)
throw std::runtime_error("Invalid ProtoBuf key '" + key + "'");
}

std::vector<std::string> ProtoBufMetaKey::getValues(const DNSQuestion& dq) const
std::vector<std::string> ProtoBufMetaKey::getValues(const DNSQuestion& dnsquestion) const
{
auto& idx = s_types.get<TypeTag>();
auto it = idx.find(d_type);
if (it == idx.end()) {
throw std::runtime_error("Trying to get the values of an unsupported type: " + std::to_string(static_cast<uint8_t>(d_type)));
}
return (it->d_func)(dq, d_subKey, d_numericSubKey);
return (it->d_func)(dnsquestion, d_subKey, d_numericSubKey);
}

const std::string& ProtoBufMetaKey::getName() const
Expand All @@ -289,97 +289,100 @@ const std::string& ProtoBufMetaKey::getName() const
}

const ProtoBufMetaKey::TypeContainer ProtoBufMetaKey::s_types = {
ProtoBufMetaKey::KeyTypeDescription{"sni", Type::SNI, [](const DNSQuestion& dq, const std::string&, uint8_t) -> std::vector<std::string> { return {dq.sni}; }, false},
ProtoBufMetaKey::KeyTypeDescription{"pool", Type::Pool, [](const DNSQuestion& dq, const std::string&, uint8_t) -> std::vector<std::string> { return {dq.ids.poolName}; }, false},
ProtoBufMetaKey::KeyTypeDescription{"b64-content", Type::B64Content, [](const DNSQuestion& dq, const std::string&, uint8_t) -> std::vector<std::string> { const auto& data = dq.getData(); return {Base64Encode(std::string(data.begin(), data.end()))}; }, false},
ProtoBufMetaKey::KeyTypeDescription{"sni", Type::SNI, [](const DNSQuestion& dnsquestion, const std::string&, uint8_t) -> std::vector<std::string> { return {dnsquestion.sni}; }, false},
ProtoBufMetaKey::KeyTypeDescription{"pool", Type::Pool, [](const DNSQuestion& dnsquestion, const std::string&, uint8_t) -> std::vector<std::string> { return {dnsquestion.ids.poolName}; }, false},
ProtoBufMetaKey::KeyTypeDescription{"b64-content", Type::B64Content, [](const DNSQuestion& dnsquestion, const std::string&, uint8_t) -> std::vector<std::string> { const auto& data = dnsquestion.getData(); return {Base64Encode(std::string(data.begin(), data.end()))}; }, false},
#ifdef HAVE_DNS_OVER_HTTPS
ProtoBufMetaKey::KeyTypeDescription{"doh-header", Type::DoHHeader, [](const DNSQuestion& dq, const std::string& name, uint8_t) -> std::vector<std::string> {
if (!dq.ids.du) {
ProtoBufMetaKey::KeyTypeDescription{"doh-header", Type::DoHHeader, [](const DNSQuestion& dnsquestion, const std::string& name, uint8_t) -> std::vector<std::string> {
if (!dnsquestion.ids.du) {
return {};
}
auto headers = dq.ids.du->getHTTPHeaders();
auto it = headers.find(name);
if (it != headers.end()) {
return {it->second};
auto headers = dnsquestion.ids.du->getHTTPHeaders();
auto iter = headers.find(name);
if (iter != headers.end()) {
return {iter->second};
}
return {};
},
true, false},
ProtoBufMetaKey::KeyTypeDescription{"doh-host", Type::DoHHost, [](const DNSQuestion& dq, const std::string&, uint8_t) -> std::vector<std::string> {
if (dq.ids.du) {
return {dq.ids.du->getHTTPHost()};
ProtoBufMetaKey::KeyTypeDescription{"doh-host", Type::DoHHost, [](const DNSQuestion& dnsquestion, const std::string&, uint8_t) -> std::vector<std::string> {
if (dnsquestion.ids.du) {
return {dnsquestion.ids.du->getHTTPHost()};
}
return {};
},
true, false},
ProtoBufMetaKey::KeyTypeDescription{"doh-path", Type::DoHPath, [](const DNSQuestion& dq, const std::string&, uint8_t) -> std::vector<std::string> {
if (dq.ids.du) {
return {dq.ids.du->getHTTPPath()};
ProtoBufMetaKey::KeyTypeDescription{"doh-path", Type::DoHPath, [](const DNSQuestion& dnsquestion, const std::string&, uint8_t) -> std::vector<std::string> {
if (dnsquestion.ids.du) {
return {dnsquestion.ids.du->getHTTPPath()};
}
return {};
},
false},
ProtoBufMetaKey::KeyTypeDescription{"doh-query-string", Type::DoHQueryString, [](const DNSQuestion& dq, const std::string&, uint8_t) -> std::vector<std::string> {
if (dq.ids.du) {
return {dq.ids.du->getHTTPQueryString()};
ProtoBufMetaKey::KeyTypeDescription{"doh-query-string", Type::DoHQueryString, [](const DNSQuestion& dnsquestion, const std::string&, uint8_t) -> std::vector<std::string> {
if (dnsquestion.ids.du) {
return {dnsquestion.ids.du->getHTTPQueryString()};
}
return {};
},
false},
ProtoBufMetaKey::KeyTypeDescription{"doh-scheme", Type::DoHScheme, [](const DNSQuestion& dq, const std::string&, uint8_t) -> std::vector<std::string> {
if (dq.ids.du) {
return {dq.ids.du->getHTTPScheme()};
ProtoBufMetaKey::KeyTypeDescription{"doh-scheme", Type::DoHScheme, [](const DNSQuestion& dnsquestion, const std::string&, uint8_t) -> std::vector<std::string> {
if (dnsquestion.ids.du) {
return {dnsquestion.ids.du->getHTTPScheme()};
}
return {};
},
false, false},
#endif // HAVE_DNS_OVER_HTTPS
ProtoBufMetaKey::KeyTypeDescription{"proxy-protocol-value", Type::ProxyProtocolValue, [](const DNSQuestion& dq, const std::string&, uint8_t numericSubKey) -> std::vector<std::string> {
if (!dq.proxyProtocolValues) {
ProtoBufMetaKey::KeyTypeDescription{"proxy-protocol-value", Type::ProxyProtocolValue, [](const DNSQuestion& dnsquestion, const std::string&, uint8_t numericSubKey) -> std::vector<std::string> {
if (!dnsquestion.proxyProtocolValues) {
return {};
}
for (const auto& value : *dq.proxyProtocolValues) {
for (const auto& value : *dnsquestion.proxyProtocolValues) {
if (value.type == numericSubKey) {
return {value.content};
}
}
return {};
},
true, false, true},
ProtoBufMetaKey::KeyTypeDescription{"proxy-protocol-values", Type::ProxyProtocolValues, [](const DNSQuestion& dq, const std::string&, uint8_t) -> std::vector<std::string> {
ProtoBufMetaKey::KeyTypeDescription{"proxy-protocol-values", Type::ProxyProtocolValues, [](const DNSQuestion& dnsquestion, const std::string&, uint8_t) -> std::vector<std::string> {
std::vector<std::string> result;
if (!dq.proxyProtocolValues) {
if (!dnsquestion.proxyProtocolValues) {
return result;
}
for (const auto& value : *dq.proxyProtocolValues) {
for (const auto& value : *dnsquestion.proxyProtocolValues) {
result.push_back(std::to_string(value.type) + ":" + value.content);
}
return result;
}},
ProtoBufMetaKey::KeyTypeDescription{"tag", Type::Tag, [](const DNSQuestion& dq, const std::string& subKey, uint8_t) -> std::vector<std::string> {
if (!dq.ids.qTag) {
ProtoBufMetaKey::KeyTypeDescription{"tag", Type::Tag, [](const DNSQuestion& dnsquestion, const std::string& subKey, uint8_t) -> std::vector<std::string> {
if (!dnsquestion.ids.qTag) {
return {};
}
for (const auto& [key, value] : *dq.ids.qTag) {
for (const auto& [key, value] : *dnsquestion.ids.qTag) {
if (key == subKey) {
return {value};
}
}
return {};
},
true, true},
ProtoBufMetaKey::KeyTypeDescription{"tags", Type::Tags, [](const DNSQuestion& dq, const std::string&, uint8_t) -> std::vector<std::string> {
ProtoBufMetaKey::KeyTypeDescription{"tags", Type::Tags, [](const DNSQuestion& dnsquestion, const std::string&, uint8_t) -> std::vector<std::string> {
std::vector<std::string> result;
if (!dq.ids.qTag) {
if (!dnsquestion.ids.qTag) {
return result;
}
for (const auto& [key, value] : *dq.ids.qTag) {
for (const auto& [key, value] : *dnsquestion.ids.qTag) {
if (value.empty()) {
/* avoids a spurious ':' when the value is empty */
result.push_back(key);
}
else {
result.push_back(key + ":" + value);
auto tag = key;
tag.append(":");
tag.append(value);
result.push_back(tag);
}
}
return result;
Expand Down
31 changes: 17 additions & 14 deletions pdns/dnsdist-protobuf.hh
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@
class DNSDistProtoBufMessage
{
public:
DNSDistProtoBufMessage(const DNSQuestion& dq);
DNSDistProtoBufMessage(const DNSResponse& dr, bool includeCNAME);
DNSDistProtoBufMessage(const DNSQuestion& dnsquestion);
DNSDistProtoBufMessage(const DNSResponse& dnsresponse, bool includeCNAME);
DNSDistProtoBufMessage(const DNSQuestion&&) = delete;
DNSDistProtoBufMessage(const DNSResponse&&, bool) = delete;

void setServerIdentity(const std::string& serverId);
void setRequestor(const ComboAddress& requestor);
Expand All @@ -45,15 +47,15 @@ public:
void setTime(time_t sec, uint32_t usec);
void setQueryTime(time_t sec, uint32_t usec);
void setQuestion(const DNSName& name, uint16_t qtype, uint16_t qclass);
void setEDNSSubnet(const Netmask& nm);
void setEDNSSubnet(const Netmask& netmask);

void addTag(const std::string& strValue);
void addMeta(const std::string& key, std::vector<std::string>&& strValues, const std::vector<int64_t>& intValues);
void addRR(DNSName&& qname, uint16_t uType, uint16_t uClass, uint32_t uTTL, const std::string& data);

void serialize(std::string& data) const;

std::string toDebugString() const;
[[nodiscard]] std::string toDebugString() const;

private:
struct PBRecord
Expand All @@ -66,8 +68,8 @@ private:
};
struct PBQuestion
{
PBQuestion(const DNSName& name, uint16_t type, uint16_t class_) :
d_name(name), d_type(type), d_class(class_)
PBQuestion(DNSName name, uint16_t type, uint16_t class_) :
d_name(std::move(name)), d_type(type), d_class(class_)
{
}

Expand All @@ -85,6 +87,8 @@ private:
};
std::unordered_map<std::string, MetaValue> d_metaTags;

// FIXME wondering if the cost of moving to a shared_ptr would be that bad
github-advanced-security[bot] marked this conversation as resolved.
Fixed
Show resolved Hide resolved
// NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members)
const DNSQuestion& d_dq;
const DNSResponse* d_dr{nullptr};
const std::string* d_ServerIdentityRef{nullptr};
Expand Down Expand Up @@ -123,9 +127,9 @@ class ProtoBufMetaKey

struct KeyTypeDescription
{
const std::string d_name;
const Type d_type;
const std::function<std::vector<std::string>(const DNSQuestion&, const std::string&, uint8_t)> d_func;
std::string d_name;
Type d_type;
std::function<std::vector<std::string>(const DNSQuestion&, const std::string&, uint8_t)> d_func;
chbruyand marked this conversation as resolved.
Show resolved Hide resolved
bool d_prefix{false};
bool d_caseSensitive{true};
bool d_numeric{false};
Expand All @@ -138,20 +142,19 @@ class ProtoBufMetaKey
{
};

typedef boost::multi_index_container<
using TypeContainer = boost::multi_index_container<
KeyTypeDescription,
indexed_by<
hashed_unique<tag<NameTag>, member<KeyTypeDescription, const std::string, &KeyTypeDescription::d_name>>,
hashed_unique<tag<TypeTag>, member<KeyTypeDescription, const Type, &KeyTypeDescription::d_type>>>>
TypeContainer;
hashed_unique<tag<TypeTag>, member<KeyTypeDescription, const Type, &KeyTypeDescription::d_type>>>>;

static const TypeContainer s_types;

public:
ProtoBufMetaKey(const std::string& key);

const std::string& getName() const;
std::vector<std::string> getValues(const DNSQuestion& dq) const;
[[nodiscard]] const std::string& getName() const;
[[nodiscard]] std::vector<std::string> getValues(const DNSQuestion& dnsquestion) const;

private:
std::string d_subKey;
Expand Down
7 changes: 7 additions & 0 deletions pdns/dnsdist.hh
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,13 @@ struct DNSQuestion
ids.qTag->insert_or_assign(key, value);
}

void setTag(const std::string& key, std::string&& value) {
if (!ids.qTag) {
ids.qTag = std::make_unique<QTag>();
}
ids.qTag->insert_or_assign(key, std::move(value));
}

const struct timespec& getQueryRealTime() const
{
return ids.queryRealTime.d_start;
Expand Down
2 changes: 1 addition & 1 deletion pdns/dnsname.cc
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ DNSName::DNSName(const std::string_view sw)
}


DNSName::DNSName(const char* pos, int len, int offset, bool uncompress, uint16_t* qtype, uint16_t* qclass, unsigned int* consumed, uint16_t minOffset)
DNSName::DNSName(const char* pos, size_t len, size_t offset, bool uncompress, uint16_t* qtype, uint16_t* qclass, unsigned int* consumed, uint16_t minOffset)
{
if (offset >= len)
throw std::range_error("Trying to read past the end of the buffer ("+std::to_string(offset)+ " >= "+std::to_string(len)+")");
Expand Down
2 changes: 1 addition & 1 deletion pdns/dnsname.hh
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public:
DNSName(DNSName&& a) = default;

explicit DNSName(std::string_view sw); //!< Constructs from a human formatted, escaped presentation
DNSName(const char* p, int len, int offset, bool uncompress, uint16_t* qtype=nullptr, uint16_t* qclass=nullptr, unsigned int* consumed=nullptr, uint16_t minOffset=0); //!< Construct from a DNS Packet, taking the first question if offset=12. If supplied, consumed is set to the number of bytes consumed from the packet, which will not be equal to the wire length of the resulting name in case of compression.
DNSName(const char* pos, size_t len, size_t offset, bool uncompress, uint16_t* qtype = nullptr, uint16_t* qclass = nullptr, unsigned int* consumed = nullptr, uint16_t minOffset = 0); //!< Construct from a DNS Packet, taking the first question if offset=12. If supplied, consumed is set to the number of bytes consumed from the packet, which will not be equal to the wire length of the resulting name in case of compression.
chbruyand marked this conversation as resolved.
Show resolved Hide resolved

bool isPartOf(const DNSName& rhs) const; //!< Are we part of the rhs name? Note that name.isPartOf(name).
inline bool operator==(const DNSName& rhs) const; //!< DNS-native comparison (case insensitive) - empty compares to empty
Expand Down
Loading