From: Anton Khirnov Date: Mon, 7 Jul 2025 09:37:19 +0000 (+0200) Subject: rec: allow forcing TCP from preoutquery() X-Git-Tag: rec-5.3.0-alpha2~2^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f13e82a7077a1973fc10e501f451642ac81d3aff;p=thirdparty%2Fpdns.git rec: allow forcing TCP from preoutquery() --- diff --git a/pdns/recursordist/docs/lua-scripting/hooks.rst b/pdns/recursordist/docs/lua-scripting/hooks.rst index 7a041e711e..aee61f2384 100644 --- a/pdns/recursordist/docs/lua-scripting/hooks.rst +++ b/pdns/recursordist/docs/lua-scripting/hooks.rst @@ -183,13 +183,17 @@ Interception Functions .. function:: preoutquery(dq) -> bool + .. versionchanged:: 5.3.0 + + `isTcp` can be set to force TCP or UDP + This hook is not called in response to a client packet, but fires when the Recursor wants to talk to an authoritative server. When this hook sets the special result code ``-3``, the whole DNS client query causing this outgoing query gets a ``ServFail``. However, this function can also return records like :func:`preresolve`. - :param DNSQuestion dq: The DNS question to handle. + :param DNSQuestion dq: Attributes of a DNS question to be sent out to an authoritative server In the case of :func:`preoutquery`, only a few attributes if the :class:`dq ` object are filled in: @@ -197,7 +201,10 @@ Interception Functions - :attr:`dq.localaddr ` - :attr:`dq.qname ` - :attr:`dq.qtype ` - - :attr:`dq.isTcp ` + - :attr:`dq.isTcp ` since version 5.3.0 this attribute may be changed by the hook to force the use of UDP or TCP + + Note that except for `dq.localaddr`, which identifies the client that triggered this outgoing query, all other attributes apply to + the *outgoing* query that will be sent by the Recursor. Do not rely on other attributes having a value and do not call any method of the :class:`dq ` object apart from the record set manipulation methods. diff --git a/pdns/recursordist/lua-recursor4.cc b/pdns/recursordist/lua-recursor4.cc index 66bdf9b20f..906d5f2c71 100644 --- a/pdns/recursordist/lua-recursor4.cc +++ b/pdns/recursordist/lua-recursor4.cc @@ -163,7 +163,7 @@ void RecursorLua4::postPrepareContext() // NOLINT(readability-function-cognitive { d_lw->registerMember("qname", [](const DNSQuestion& dnsQuestion) -> const DNSName& { return dnsQuestion.qname; }, [](DNSQuestion& /* dnsQuestion */, const DNSName& newName) { (void) newName; }); d_lw->registerMember("qtype", [](const DNSQuestion& dnsQuestion) -> uint16_t { return dnsQuestion.qtype; }, [](DNSQuestion& /* dnsQuestion */, uint16_t newType) { (void) newType; }); - d_lw->registerMember("isTcp", [](const DNSQuestion& dnsQuestion) -> bool { return dnsQuestion.isTcp; }, [](DNSQuestion& /* dnsQuestion */, bool newTcp) { (void) newTcp; }); + d_lw->registerMember("isTcp", [](const DNSQuestion& dnsQuestion) -> bool { return dnsQuestion.isTcp; }, [](DNSQuestion& dnsQuestion, bool newTcp) { dnsQuestion.isTcp = newTcp; }); d_lw->registerMember("localaddr", [](const DNSQuestion& dnsQuestion) -> const ComboAddress& { return dnsQuestion.local; }, [](DNSQuestion& /* dnsQuestion */, const ComboAddress& newLocal) { (void) newLocal; }); d_lw->registerMember("remoteaddr", [](const DNSQuestion& dnsQuestion) -> const ComboAddress& { return dnsQuestion.remote; }, [](DNSQuestion& /* dnsQuestion */, const ComboAddress& newRemote) { (void) newRemote; }); d_lw->registerMember("interface_localaddr", [](const DNSQuestion& dnsQuestion) -> const ComboAddress& { return dnsQuestion.interface_local; }, [](DNSQuestion& /* dnsQuestion */, const ComboAddress& newLocal) { (void) newLocal; }); @@ -652,7 +652,7 @@ bool RecursorLua4::postresolve(DNSQuestion& dnsQuestion, int& ret, RecEventTrace return isOK; } -bool RecursorLua4::preoutquery(const ComboAddress& nameserver, const ComboAddress& requestor, const DNSName& query, const QType& qtype, bool isTcp, vector& res, int& ret, RecEventTrace& eventTrace, const struct timeval& theTime) const +bool RecursorLua4::preoutquery(const ComboAddress& nameserver, const ComboAddress& requestor, const DNSName& query, const QType& qtype, bool& isTcp, vector& res, int& ret, RecEventTrace& eventTrace, const struct timeval& theTime) const { if (!d_preoutquery) { return false; @@ -667,6 +667,9 @@ bool RecursorLua4::preoutquery(const ComboAddress& nameserver, const ComboAddres bool isOK = genhook(d_preoutquery, dnsQuestion, ret); eventTrace.add(RecEventTrace::LuaPreOutQuery, isOK, false, match); warnDrop(dnsQuestion); + + isTcp = dnsQuestion.isTcp; + return isOK; } diff --git a/pdns/recursordist/lua-recursor4.hh b/pdns/recursordist/lua-recursor4.hh index 375a3b9fe0..0d3874f07d 100644 --- a/pdns/recursordist/lua-recursor4.hh +++ b/pdns/recursordist/lua-recursor4.hh @@ -137,7 +137,7 @@ public: unsigned int tag{0}; int rcode{0}; const uint16_t qtype; - const bool isTcp; + bool isTcp; vState validationState{vState::Indeterminate}; void addAnswer(uint16_t type, const std::string& content, boost::optional ttl, boost::optional name); @@ -219,7 +219,7 @@ public: bool nodata(DNSQuestion& dnsQuestion, int& ret, RecEventTrace&) const; bool postresolve(DNSQuestion& dnsQuestion, int& ret, RecEventTrace&) const; - bool preoutquery(const ComboAddress& nameserver, const ComboAddress& requestor, const DNSName& query, const QType& qtype, bool isTcp, vector& res, int& ret, RecEventTrace& eventTrace, const struct timeval& theTime) const; + bool preoutquery(const ComboAddress& nameserver, const ComboAddress& requestor, const DNSName& query, const QType& qtype, bool& isTcp, vector& res, int& ret, RecEventTrace& eventTrace, const struct timeval& theTime) const; bool ipfilter(const ComboAddress& remote, const ComboAddress& local, const struct dnsheader&, RecEventTrace&) const; bool policyHitEventFilter(const ComboAddress& remote, const DNSName& qname, const QType& qtype, bool tcp, DNSFilterEngine::Policy& policy, std::unordered_set& tags, std::unordered_map& discardedPolicies) const; diff --git a/pdns/recursordist/test-syncres_cc.cc b/pdns/recursordist/test-syncres_cc.cc index a38c156943..344f7cc51a 100644 --- a/pdns/recursordist/test-syncres_cc.cc +++ b/pdns/recursordist/test-syncres_cc.cc @@ -38,7 +38,7 @@ void BaseLua4::getFeatures(Features& /* features */) { } -bool RecursorLua4::preoutquery(const ComboAddress& /* ns */, const ComboAddress& /* requestor */, const DNSName& /* query */, const QType& /* qtype */, bool /* isTcp */, vector& /* res */, int& /* ret */, RecEventTrace& /* et */, const struct timeval& /* tv */) const +bool RecursorLua4::preoutquery(const ComboAddress& /* ns */, const ComboAddress& /* requestor */, const DNSName& /* query */, const QType& /* qtype */, bool& /* isTcp */, vector& /* res */, int& /* ret */, RecEventTrace& /* et */, const struct timeval& /* tv */) const { return false; }