From: Remi Gacogne Date: Wed, 26 Feb 2020 17:25:24 +0000 (+0100) Subject: rec: Export Proxy Protocol values to gettag hooks X-Git-Tag: dnsdist-1.5.0-alpha1~12^2~23 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3bdc450869b0824c2cd959c7ce243aca214d175b;p=thirdparty%2Fpdns.git rec: Export Proxy Protocol values to gettag hooks --- diff --git a/pdns/lua-recursor4-ffi.hh b/pdns/lua-recursor4-ffi.hh index 47396a8386..d852fbeb05 100644 --- a/pdns/lua-recursor4-ffi.hh +++ b/pdns/lua-recursor4-ffi.hh @@ -29,6 +29,12 @@ extern "C" { const void* data; } pdns_ednsoption_t; + typedef struct pdns_proxyprotocol_value { + uint8_t type; + uint16_t len; + const void* data; + } pdns_proxyprotocol_value_t; + typedef enum { answer = 1, @@ -53,6 +59,9 @@ extern "C" { size_t pdns_ffi_param_get_edns_options(pdns_ffi_param_t* ref, const pdns_ednsoption_t** out) __attribute__ ((visibility ("default"))); size_t pdns_ffi_param_get_edns_options_by_code(pdns_ffi_param_t* ref, uint16_t optionCode, const pdns_ednsoption_t** out) __attribute__ ((visibility ("default"))); + // returns the length of the resulting 'out' array. 'out' is not set if the length is 0 + size_t pdns_ffi_param_get_proxy_protocol_values(pdns_ffi_param_t* ref, const pdns_proxyprotocol_value_t** out) __attribute__ ((visibility ("default"))); + void pdns_ffi_param_set_tag(pdns_ffi_param_t* ref, unsigned int tag) __attribute__ ((visibility ("default"))); void pdns_ffi_param_add_policytag(pdns_ffi_param_t *ref, const char* name) __attribute__ ((visibility ("default"))); void pdns_ffi_param_set_requestorid(pdns_ffi_param_t* ref, const char* name) __attribute__ ((visibility ("default"))); diff --git a/pdns/lua-recursor4.cc b/pdns/lua-recursor4.cc index e8b413f2eb..404a773d8d 100644 --- a/pdns/lua-recursor4.cc +++ b/pdns/lua-recursor4.cc @@ -183,14 +183,15 @@ boost::optional RecursorLua4::DNSQuestion::getEDNSSubnet() const return boost::optional(); } -std::vector> RecursorLua4::DNSQuestion::getProxyProtocolValues() const +std::vector> RecursorLua4::DNSQuestion::getProxyProtocolValues() const { - std::vector> result; + std::vector> result; if (proxyProtocolValues) { result.reserve(proxyProtocolValues->size()); + int idx = 1; for (const auto& value: *proxyProtocolValues) { - result.push_back({ value.type, value.content }); + result.push_back({ idx++, value }); } } @@ -350,6 +351,8 @@ void RecursorLua4::postPrepareContext() return ret; }); + d_lw->registerFunction("getContent", [](const ProxyProtocolValue& value) { return value.content; }); + d_lw->registerFunction("getType", [](const ProxyProtocolValue& value) { return value.type; }); d_lw->registerFunction("changeContent", [](DNSRecord& dr, const std::string& newContent) { dr.d_content = DNSRecordContent::mastermake(dr.d_type, 1, newContent); }); d_lw->registerFunction("addAnswer", &DNSQuestion::addAnswer); @@ -534,10 +537,17 @@ bool RecursorLua4::ipfilter(const ComboAddress& remote, const ComboAddress& loca return false; // don't block } -unsigned int RecursorLua4::gettag(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype, std::vector* policyTags, LuaContext::LuaObject& data, const EDNSOptionViewMap& ednsOptions, bool tcp, std::string& requestorId, std::string& deviceId, std::string& deviceName) const +unsigned int RecursorLua4::gettag(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype, std::vector* policyTags, LuaContext::LuaObject& data, const EDNSOptionViewMap& ednsOptions, bool tcp, std::string& requestorId, std::string& deviceId, std::string& deviceName, const std::vector& proxyProtocolValues) const { if(d_gettag) { - auto ret = d_gettag(remote, ednssubnet, local, qname, qtype, ednsOptions, tcp); + std::vector> proxyProtocolValuesMap; + proxyProtocolValuesMap.reserve(proxyProtocolValues.size()); + int num = 1; + for (const auto& value : proxyProtocolValues) { + proxyProtocolValuesMap.emplace_back(num++, &value); + } + + auto ret = d_gettag(remote, ednssubnet, local, qname, qtype, ednsOptions, tcp, proxyProtocolValuesMap); if (policyTags) { const auto& tags = std::get<1>(ret); @@ -572,7 +582,7 @@ unsigned int RecursorLua4::gettag(const ComboAddress& remote, const Netmask& edn struct pdns_ffi_param { public: - pdns_ffi_param(const DNSName& qname_, uint16_t qtype_, const ComboAddress& local_, const ComboAddress& remote_, const Netmask& ednssubnet_, std::vector& policyTags_, std::vector& records_, const EDNSOptionViewMap& ednsOptions_, std::string& requestorId_, std::string& deviceId_, std::string& deviceName_, boost::optional& rcode_, uint32_t& ttlCap_, bool& variable_, bool tcp_, bool& logQuery_, bool& logResponse_, bool& followCNAMERecords_): qname(qname_), local(local_), remote(remote_), ednssubnet(ednssubnet_), policyTags(policyTags_), records(records_), ednsOptions(ednsOptions_), requestorId(requestorId_), deviceId(deviceId_), deviceName(deviceName_), rcode(rcode_), ttlCap(ttlCap_), variable(variable_), logQuery(logQuery_), logResponse(logResponse_), followCNAMERecords(followCNAMERecords_), qtype(qtype_), tcp(tcp_) + pdns_ffi_param(const DNSName& qname_, uint16_t qtype_, const ComboAddress& local_, const ComboAddress& remote_, const Netmask& ednssubnet_, std::vector& policyTags_, std::vector& records_, const EDNSOptionViewMap& ednsOptions_, const std::vector& proxyProtocolValues_, std::string& requestorId_, std::string& deviceId_, std::string& deviceName_, boost::optional& rcode_, uint32_t& ttlCap_, bool& variable_, bool tcp_, bool& logQuery_, bool& logResponse_, bool& followCNAMERecords_): qname(qname_), local(local_), remote(remote_), ednssubnet(ednssubnet_), policyTags(policyTags_), records(records_), ednsOptions(ednsOptions_), proxyProtocolValues(proxyProtocolValues_), requestorId(requestorId_), deviceId(deviceId_), deviceName(deviceName_), rcode(rcode_), ttlCap(ttlCap_), variable(variable_), logQuery(logQuery_), logResponse(logResponse_), followCNAMERecords(followCNAMERecords_), qtype(qtype_), tcp(tcp_) { } @@ -581,6 +591,7 @@ public: std::unique_ptr remoteStr{nullptr}; std::unique_ptr ednssubnetStr{nullptr}; std::vector ednsOptionsVect; + std::vector proxyProtocolValuesVect; const DNSName& qname; const ComboAddress& local; @@ -589,6 +600,7 @@ public: std::vector& policyTags; std::vector& records; const EDNSOptionViewMap& ednsOptions; + const std::vector& proxyProtocolValues; std::string& requestorId; std::string& deviceId; std::string& deviceName; @@ -604,10 +616,10 @@ public: bool tcp; }; -unsigned int RecursorLua4::gettag_ffi(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype, std::vector* policyTags, std::vector& records, LuaContext::LuaObject& data, const EDNSOptionViewMap& ednsOptions, bool tcp, std::string& requestorId, std::string& deviceId, std::string& deviceName, boost::optional& rcode, uint32_t& ttlCap, bool& variable, bool& logQuery, bool& logResponse, bool& followCNAMERecords) const +unsigned int RecursorLua4::gettag_ffi(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype, std::vector* policyTags, std::vector& records, LuaContext::LuaObject& data, const EDNSOptionViewMap& ednsOptions, bool tcp, const std::vector& proxyProtocolValues, std::string& requestorId, std::string& deviceId, std::string& deviceName, boost::optional& rcode, uint32_t& ttlCap, bool& variable, bool& logQuery, bool& logResponse, bool& followCNAMERecords) const { if (d_gettag_ffi) { - pdns_ffi_param_t param(qname, qtype, local, remote, ednssubnet, *policyTags, records, ednsOptions, requestorId, deviceId, deviceName, rcode, ttlCap, variable, tcp, logQuery, logResponse, followCNAMERecords); + pdns_ffi_param_t param(qname, qtype, local, remote, ednssubnet, *policyTags, records, ednsOptions, proxyProtocolValues, requestorId, deviceId, deviceName, rcode, ttlCap, variable, tcp, logQuery, logResponse, followCNAMERecords); auto ret = d_gettag_ffi(¶m); if (ret) { @@ -837,6 +849,30 @@ size_t pdns_ffi_param_get_edns_options_by_code(pdns_ffi_param_t* ref, uint16_t o return pos; } +size_t pdns_ffi_param_get_proxy_protocol_values(pdns_ffi_param_t* ref, const pdns_proxyprotocol_value_t** out) +{ + if (ref->proxyProtocolValues.empty()) { + return 0; + } + + ref->proxyProtocolValuesVect.resize(ref->proxyProtocolValues.size()); + + size_t pos = 0; + for (const auto& value : ref->proxyProtocolValues) { + auto& dest = ref->proxyProtocolValuesVect.at(pos); + dest.type = value.type; + dest.len = value.content.size(); + if (dest.len > 0) { + dest.data = value.content.data(); + } + pos++; + } + + *out = ref->proxyProtocolValuesVect.data(); + + return ref->proxyProtocolValuesVect.size(); +} + void pdns_ffi_param_set_tag(pdns_ffi_param_t* ref, unsigned int tag) { ref->tag = tag; diff --git a/pdns/lua-recursor4.hh b/pdns/lua-recursor4.hh index 8e3e082bd7..88bf6fea8c 100644 --- a/pdns/lua-recursor4.hh +++ b/pdns/lua-recursor4.hh @@ -94,7 +94,7 @@ public: vector > getEDNSOptions() const; boost::optional getEDNSOption(uint16_t code) const; boost::optional getEDNSSubnet() const; - std::vector> getProxyProtocolValues() const; + std::vector> getProxyProtocolValues() const; vector getEDNSFlags() const; bool getEDNSFlag(string flag) const; void setRecords(const vector >& records); @@ -115,8 +115,8 @@ public: DNSName followupName; }; - unsigned int gettag(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype, std::vector* policyTags, LuaContext::LuaObject& data, const EDNSOptionViewMap&, bool tcp, std::string& requestorId, std::string& deviceId, std::string& deviceName) const; - unsigned int gettag_ffi(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype, std::vector* policyTags, std::vector& records, LuaContext::LuaObject& data, const EDNSOptionViewMap& ednsOptions, bool tcp, std::string& requestorId, std::string& deviceId, std::string& deviceName, boost::optional& rcode, uint32_t& ttlCap, bool& variable, bool& logQuery, bool& logResponse, bool& followCNAMERecords) const; + unsigned int gettag(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype, std::vector* policyTags, LuaContext::LuaObject& data, const EDNSOptionViewMap&, bool tcp, std::string& requestorId, std::string& deviceId, std::string& deviceName, const std::vector& proxyProtocolValues) const; + unsigned int gettag_ffi(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype, std::vector* policyTags, std::vector& records, LuaContext::LuaObject& data, const EDNSOptionViewMap& ednsOptions, bool tcp, const std::vector& proxyProtocolValues, std::string& requestorId, std::string& deviceId, std::string& deviceName, boost::optional& rcode, uint32_t& ttlCap, bool& variable, bool& logQuery, bool& logResponse, bool& followCNAMERecords) const; void maintenance() const; bool prerpz(DNSQuestion& dq, int& ret) const; @@ -137,7 +137,7 @@ public: d_postresolve); } - typedef std::function >,boost::optional,boost::optional,boost::optional,boost::optional >(ComboAddress, Netmask, ComboAddress, DNSName, uint16_t, const EDNSOptionViewMap&, bool)> gettag_t; + typedef std::function >,boost::optional,boost::optional,boost::optional,boost::optional >(ComboAddress, Netmask, ComboAddress, DNSName, uint16_t, const EDNSOptionViewMap&, bool, const std::vector>&)> gettag_t; gettag_t d_gettag; // public so you can query if we have this hooked typedef std::function(pdns_ffi_param_t*)> gettag_ffi_t; gettag_ffi_t d_gettag_ffi; diff --git a/pdns/pdns_recursor.cc b/pdns/pdns_recursor.cc index f20c1174e4..24a94fcd88 100644 --- a/pdns/pdns_recursor.cc +++ b/pdns/pdns_recursor.cc @@ -2032,6 +2032,9 @@ static void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var) conn->data.resize(conn->proxyProtocolGot); ssize_t remaining = isProxyHeaderComplete(conn->data); if (remaining == 0) { + if (g_logCommonErrors) { + g_log<d_remote.toStringWithPort() <removeReadFD(fd); return; @@ -2048,6 +2051,10 @@ static void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var) bool tcp; bool proxy = false; if (parseProxyHeader(conn->data, proxy, conn->d_source, conn->d_destination, tcp, conn->proxyProtocolValues) <= 0) { + if (g_logCommonErrors) { + g_log<d_remote.toStringWithPort() <removeReadFD(fd); return; } @@ -2182,10 +2189,10 @@ static void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var) if(t_pdl) { try { if (t_pdl->d_gettag_ffi) { - dc->d_tag = t_pdl->gettag_ffi(dc->d_source, dc->d_ednssubnet.source, dc->d_destination, qname, qtype, &dc->d_policyTags, dc->d_records, dc->d_data, ednsOptions, true, requestorId, deviceId, deviceName, dc->d_rcode, dc->d_ttlCap, dc->d_variable, logQuery, dc->d_logResponse, dc->d_followCNAMERecords); + dc->d_tag = t_pdl->gettag_ffi(dc->d_source, dc->d_ednssubnet.source, dc->d_destination, qname, qtype, &dc->d_policyTags, dc->d_records, dc->d_data, ednsOptions, true, dc->d_proxyProtocolValues, requestorId, deviceId, deviceName, dc->d_rcode, dc->d_ttlCap, dc->d_variable, logQuery, dc->d_logResponse, dc->d_followCNAMERecords); } else if (t_pdl->d_gettag) { - dc->d_tag = t_pdl->gettag(dc->d_source, dc->d_ednssubnet.source, dc->d_destination, qname, qtype, &dc->d_policyTags, dc->d_data, ednsOptions, true, requestorId, deviceId, deviceName); + dc->d_tag = t_pdl->gettag(dc->d_source, dc->d_ednssubnet.source, dc->d_destination, qname, qtype, &dc->d_policyTags, dc->d_data, ednsOptions, true, requestorId, deviceId, deviceName, dc->d_proxyProtocolValues); } } catch(const std::exception& e) { @@ -2440,10 +2447,10 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr if(t_pdl) { try { if (t_pdl->d_gettag_ffi) { - ctag = t_pdl->gettag_ffi(source, ednssubnet.source, destination, qname, qtype, &policyTags, records, data, ednsOptions, false, requestorId, deviceId, deviceName, rcode, ttlCap, variable, logQuery, logResponse, followCNAMEs); + ctag = t_pdl->gettag_ffi(source, ednssubnet.source, destination, qname, qtype, &policyTags, records, data, ednsOptions, false, proxyProtocolValues, requestorId, deviceId, deviceName, rcode, ttlCap, variable, logQuery, logResponse, followCNAMEs); } else if (t_pdl->d_gettag) { - ctag = t_pdl->gettag(source, ednssubnet.source, destination, qname, qtype, &policyTags, data, ednsOptions, false, requestorId, deviceId, deviceName); + ctag = t_pdl->gettag(source, ednssubnet.source, destination, qname, qtype, &policyTags, data, ednsOptions, false, requestorId, deviceId, deviceName, proxyProtocolValues); } } catch(const std::exception& e) { @@ -2638,7 +2645,7 @@ static void handleNewUDPQuestion(int fd, FDMultiplexer::funcparam_t& var) if (used <= 0) { ++g_stats.proxyProtocolInvalidCount; if (!g_quiet) { - g_log<match(&source)) { if(!g_quiet) { - g_log<getTid()<<"] dropping UDP query from "<getTid()<<"] dropping UDP query from "<