From: Remi Gacogne Date: Mon, 7 Nov 2022 16:47:16 +0000 (+0100) Subject: dnsdist: Implement DNSResponseAction.Truncate and TCResponseAction() X-Git-Tag: dnsdist-1.9.0-alpha4~4^2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3e3081b3e5d231b36070ff80dac592e1ecd102e0;p=thirdparty%2Fpdns.git dnsdist: Implement DNSResponseAction.Truncate and TCResponseAction() To be able to truncate already existing answers. --- diff --git a/pdns/dnsdist-console.cc b/pdns/dnsdist-console.cc index b3c2443456..ee85726482 100644 --- a/pdns/dnsdist-console.cc +++ b/pdns/dnsdist-console.cc @@ -798,6 +798,7 @@ const std::vector g_consoleKeywords{ { "TagRule", true, "name [, value]", "matches if the tag named 'name' is present, with the given 'value' matching if any" }, { "TCAction", true, "", "create answer to query with TC and RD bits set, to move to TCP" }, { "TCPRule", true, "[tcp]", "Matches question received over TCP if tcp is true, over UDP otherwise" }, + { "TCResponseAction", true, "", "truncate a response" }, { "TeeAction", true, "remote [, addECS [, local]]", "send copy of query to remote, optionally adding ECS info, optionally set local address" }, { "testCrypto", true, "", "test of the crypto all works" }, { "TimedIPSetRule", true, "", "Create a rule which matches a set of IP addresses which expire"}, diff --git a/pdns/dnsdist-lua-actions.cc b/pdns/dnsdist-lua-actions.cc index dabe0b8dac..eb34ca125c 100644 --- a/pdns/dnsdist-lua-actions.cc +++ b/pdns/dnsdist-lua-actions.cc @@ -513,6 +513,19 @@ public: } }; +class TCResponseAction : public DNSResponseAction +{ +public: + DNSResponseAction::Action operator()(DNSResponse* dnsResponse, std::string* ruleresult) const override + { + return Action::Truncate; + } + std::string toString() const override + { + return "tc=1 answer"; + } +}; + class LuaAction : public DNSAction { public: @@ -2538,6 +2551,10 @@ void setupLuaActions(LuaContext& luaCtx) return std::shared_ptr(new TCAction); }); + luaCtx.writeFunction("TCResponseAction", []() { + return std::shared_ptr(new TCResponseAction); + }); + luaCtx.writeFunction("SetDisableValidationAction", []() { return std::shared_ptr(new SetDisableValidationAction); }); diff --git a/pdns/dnsdist-lua-vars.cc b/pdns/dnsdist-lua-vars.cc index 265568f9ff..89927b7245 100644 --- a/pdns/dnsdist-lua-vars.cc +++ b/pdns/dnsdist-lua-vars.cc @@ -51,6 +51,7 @@ void setupLuaVars(LuaContext& luaCtx) {"Drop", (int)DNSResponseAction::Action::Drop }, {"HeaderModify", (int)DNSResponseAction::Action::HeaderModify }, {"ServFail", (int)DNSResponseAction::Action::ServFail }, + {"Truncate", (int)DNSResponseAction::Action::Truncate }, {"None", (int)DNSResponseAction::Action::None } }); diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index 77c7f8d3a9..69dea53f08 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -532,6 +532,18 @@ static bool applyRulesToResponse(const std::vector& r }); return true; break; + case DNSResponseAction::Action::Truncate: + if (!dr.overTCP()) { + dnsdist::PacketMangling::editDNSHeaderFromPacket(dr.getMutableData(), [](dnsheader& header) { + header.tc = true; + header.qr = true; + return true; + }); + truncateTC(dr.getMutableData(), dr.getMaximumSize(), dr.ids.qname.wirelength()); + ++dnsdist::metrics::g_stats.ruleTruncated; + return true; + } + break; /* non-terminal actions follow */ case DNSResponseAction::Action::Delay: pdns::checked_stoi_into(dr.ids.delayMsec, ruleresult); // sorry diff --git a/pdns/dnsdist.hh b/pdns/dnsdist.hh index aa64c3f0c3..79e81159ac 100644 --- a/pdns/dnsdist.hh +++ b/pdns/dnsdist.hh @@ -266,7 +266,7 @@ public: class DNSResponseAction { public: - enum class Action : uint8_t { Allow, Delay, Drop, HeaderModify, ServFail, None }; + enum class Action : uint8_t { Allow, Delay, Drop, HeaderModify, ServFail, Truncate, None }; virtual Action operator()(DNSResponse*, string* ruleresult) const =0; virtual ~DNSResponseAction() { diff --git a/pdns/dnsdistdist/dnsdist-lua-ffi.hh b/pdns/dnsdistdist/dnsdist-lua-ffi.hh index d0ed83341d..a91003b971 100644 --- a/pdns/dnsdistdist/dnsdist-lua-ffi.hh +++ b/pdns/dnsdistdist/dnsdist-lua-ffi.hh @@ -48,11 +48,11 @@ struct dnsdist_ffi_dnsquestion_t DNSQuestion* dq{nullptr}; ComboAddress maskedRemote; std::string trailingData; - boost::optional result{boost::none}; - boost::optional httpPath{boost::none}; - boost::optional httpQueryString{boost::none}; - boost::optional httpHost{boost::none}; - boost::optional httpScheme{boost::none}; + std::optional result{std::nullopt}; + std::optional httpPath{std::nullopt}; + std::optional httpQueryString{std::nullopt}; + std::optional httpHost{std::nullopt}; + std::optional httpScheme{std::nullopt}; std::unique_ptr> ednsOptionsVect; std::unique_ptr> httpHeadersVect; std::unique_ptr> tagsVect; @@ -78,7 +78,7 @@ struct dnsdist_ffi_dnsresponse_t } DNSResponse* dr{nullptr}; - boost::optional result{boost::none}; + std::optional result{std::nullopt}; }; // dnsdist_ffi_server_t is a lightuserdata diff --git a/pdns/dnsdistdist/docs/reference/constants.rst b/pdns/dnsdistdist/docs/reference/constants.rst index c391741b26..e5300da5ef 100755 --- a/pdns/dnsdistdist/docs/reference/constants.rst +++ b/pdns/dnsdistdist/docs/reference/constants.rst @@ -154,6 +154,9 @@ All named `QTypes 0: + content = content + ' ' + content = content + 'A' * 255 + rrset = dns.rrset.from_text(name, + 3600, + dns.rdataclass.IN, + dns.rdatatype.TXT, + content) + backendResponse.answer.append(rrset) + self.assertGreater(len(backendResponse.to_wire()), self._payloadSize) + + (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response=backendResponse) + self.assertTrue(receivedQuery) + self.assertTrue(receivedResponse) + self.assertEqual(receivedResponse, expectedResponse) + + (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response=backendResponse) + self.assertTrue(receivedQuery) + self.assertTrue(receivedResponse) + self.assertEqual(receivedResponse, backendResponse)