From 4898a34807043c2af442ef983f9ef45e0b473651 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Fri, 4 Nov 2016 17:28:22 +0100 Subject: [PATCH] rec: Log outgoing queries / incoming responses via protobuf --- contrib/ProtobufLogger.py | 15 +++--- docs/markdown/recursor/settings.md | 16 ++++++ pdns/dnsdist-protobuf.cc | 7 +-- pdns/dnsmessage.proto | 3 ++ pdns/dnspcap2protobuf.cc | 1 + pdns/lwres.cc | 75 ++++++++++++++++++++++++++-- pdns/lwres.hh | 4 +- pdns/pdns_recursor.cc | 20 ++++++-- pdns/protobuf.cc | 47 ++++++++++++++--- pdns/protobuf.hh | 6 ++- pdns/rec-lua-conf.cc | 18 +++++++ pdns/rec-lua-conf.hh | 1 + pdns/recursordist/Makefile.am | 1 + pdns/recursordist/resolve-context.hh | 1 + pdns/resolve-context.hh | 22 ++++++++ pdns/secpoll-recursor.cc | 6 ++- pdns/syncres.cc | 7 ++- pdns/syncres.hh | 16 +++++- pdns/validate-recursor.cc | 12 ++++- pdns/validate-recursor.hh | 3 +- 20 files changed, 243 insertions(+), 38 deletions(-) create mode 120000 pdns/recursordist/resolve-context.hh create mode 100644 pdns/resolve-context.hh diff --git a/contrib/ProtobufLogger.py b/contrib/ProtobufLogger.py index 0983e1d43..5075e43f7 100644 --- a/contrib/ProtobufLogger.py +++ b/contrib/ProtobufLogger.py @@ -30,11 +30,10 @@ class PDNSPBConnHandler(object): self.printQueryMessage(msg) elif msg.type == dnsmessage_pb2.PBDNSMessage.DNSResponseType: self.printResponseMessage(msg) - # PR #3869 - # elif msg.type == dnsmessage_pb2.PBDNSMessage.DNSOutgoingQueryType: - # self.printOutgoingQueryMessage(msg) - # elif msg.type == dnsmessage_pb2.PBDNSMessage.DNSIncomingResponseType: - # self.printIncomingResponseMessage(msg) + elif msg.type == dnsmessage_pb2.PBDNSMessage.DNSOutgoingQueryType: + self.printOutgoingQueryMessage(msg) + elif msg.type == dnsmessage_pb2.PBDNSMessage.DNSIncomingResponseType: + self.printIncomingResponseMessage(msg) else: print('Discarding unsupported message type %d' % (msg.type)) @@ -137,9 +136,9 @@ class PDNSPBConnHandler(object): messageidstr = binascii.hexlify(bytearray(msg.messageId)) initialrequestidstr = '' - # PR #3869 - # if msg.HasField('initialRequestId'): - # initialrequestidstr = ', initial uuid: ' + binascii.hexlify(bytearray(msg.initialRequestId)) + if msg.HasField('initialRequestId'): + initialrequestidstr = ', initial uuid: ' + binascii.hexlify(bytearray(msg.initialRequestId)) + requestorstr = '' requestor = self.getRequestorSubnet(msg) if requestor: diff --git a/docs/markdown/recursor/settings.md b/docs/markdown/recursor/settings.md index ed39a8021..0bf60c2a2 100644 --- a/docs/markdown/recursor/settings.md +++ b/docs/markdown/recursor/settings.md @@ -545,6 +545,22 @@ The optional parameters are: * asyncConnect = if set to false (default) the first connection to the server during startup will block up to `timeout` seconds, otherwise the connection is done in a separate thread. +While `protobufServer()` only exports the queries sent to the recursor from clients, with the corresponding responses, +`outgoingProtobufServer()` can be used to export outgoing queries sent by the recursor to authoritative servers, +along with the corresponding responses. + +``` +outgoingProtobufServer("192.0.2.1:4242" [[[[, timeout], maxQueuedEntries], reconnectWaitTime], asynConnect]) +``` + +The optional parameters for `outgoingProtobufServer()` are: + +* timeout = time in seconds to wait when sending a message, default to 2 +* maxQueuedEntries = how many entries will be kept in memory if the server becomes unreachable, default to 100 +* reconnectWaitTime = how long to wait, in seconds, between two reconnection attempts, default to 1 +* asyncConnect = if set to false (default) the first connection to the server during startup will block up to `timeout` seconds, +otherwise the connection is done in a separate thread. + The protocol buffers message types can be found in the [`dnsmessage.proto`](https://github.com/PowerDNS/pdns/blob/master/pdns/dnsmessage.proto) file. ## `lua-dns-script` diff --git a/pdns/dnsdist-protobuf.cc b/pdns/dnsdist-protobuf.cc index a399a38c7..1d2a1e37d 100644 --- a/pdns/dnsdist-protobuf.cc +++ b/pdns/dnsdist-protobuf.cc @@ -22,9 +22,7 @@ #include "config.h" #include "dnsdist.hh" -#include "gettime.hh" -#include "dnsparser.hh" #include "dnsdist-protobuf.hh" #ifdef HAVE_PROTOBUF @@ -33,10 +31,7 @@ DNSDistProtoBufMessage::DNSDistProtoBufMessage(DNSProtoBufMessageType type, const DNSQuestion& dq): DNSProtoBufMessage(type, dq.uniqueId, dq.remote, dq.local, *dq.qname, dq.qtype, dq.qclass, dq.dh->id, dq.tcp, dq.len) { if (type == Response) { - PBDNSMessage_DNSResponse* response = d_message.mutable_response(); - if (response) { - response->set_rcode(dq.dh->rcode); - } + setResponseCode(dq.dh->rcode); addRRsFromPacket((const char*) dq.dh, dq.len); } }; diff --git a/pdns/dnsmessage.proto b/pdns/dnsmessage.proto index e5acc5bc5..d64de370c 100644 --- a/pdns/dnsmessage.proto +++ b/pdns/dnsmessage.proto @@ -25,6 +25,8 @@ message PBDNSMessage { enum Type { DNSQueryType = 1; DNSResponseType = 2; + DNSOutgoingQueryType = 3; + DNSIncomingResponseType = 4; } enum SocketFamily { INET = 1; // IPv4 (RFC 791) @@ -72,4 +74,5 @@ message PBDNSMessage { optional DNSResponse response = 13; optional bytes originalRequestorSubnet = 14; // EDNS Client Subnet value optional string requestorId = 15; // Username of the requestor + optional bytes initialRequestId = 16; // UUID of the incoming query that initiated this outgoing query or incoming response } diff --git a/pdns/dnspcap2protobuf.cc b/pdns/dnspcap2protobuf.cc index e36ae8698..5b7ead080 100644 --- a/pdns/dnspcap2protobuf.cc +++ b/pdns/dnspcap2protobuf.cc @@ -27,6 +27,7 @@ #include "iputils.hh" #include "misc.hh" +#include "protobuf.hh" #include "dns.hh" #include "dnspcap.hh" #include "dnsparser.hh" diff --git a/pdns/lwres.cc b/pdns/lwres.cc index a3428dce6..dd2514457 100644 --- a/pdns/lwres.cc +++ b/pdns/lwres.cc @@ -48,21 +48,60 @@ #include "validate-recursor.hh" #include "ednssubnet.hh" +#ifdef HAVE_PROTOBUF + +static void logOutgoingQuery(std::shared_ptr outgoingLogger, boost::optional initialRequestId, const boost::uuids::uuid& uuid, const ComboAddress& ip, const DNSName& domain, int type, uint16_t qid, bool doTCP, size_t bytes) +{ + if(!outgoingLogger) + return; + + RecProtoBufMessage message(DNSProtoBufMessage::OutgoingQuery, uuid, nullptr, &ip, domain, type, QClass::IN, qid, doTCP, bytes); + if (initialRequestId) { + message.setInitialRequestID(*initialRequestId); + } + +// cerr <queueData(str); +} + +static void logIncomingResponse(std::shared_ptr outgoingLogger, boost::optional initialRequestId, const boost::uuids::uuid& uuid, const ComboAddress& ip, const DNSName& domain, int type, uint16_t qid, bool doTCP, size_t bytes, int rcode, const std::vector& records, const struct timeval& queryTime) +{ + if(!outgoingLogger) + return; + + RecProtoBufMessage message(DNSProtoBufMessage::IncomingResponse, uuid, nullptr, &ip, domain, type, QClass::IN, qid, doTCP, bytes); + if (initialRequestId) { + message.setInitialRequestID(*initialRequestId); + } + message.setQueryTime(queryTime.tv_sec, queryTime.tv_usec); + message.setResponseCode(rcode); + message.addRRs(records); + +// cerr <queueData(str); +} +#endif /* HAVE_PROTOBUF */ + //! returns -2 for OS limits error, -1 for permanent error that has to do with remote **transport**, 0 for timeout, 1 for success /** lwr is only filled out in case 1 was returned, and even when returning 1 for 'success', lwr might contain DNS errors Never throws! */ -int asyncresolve(const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional& srcmask, LWResult *lwr) +int asyncresolve(const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional& srcmask, boost::optional context, std::shared_ptr outgoingLogger, LWResult *lwr) { size_t len; size_t bufsize=g_outgoingEDNSBufsize; scoped_array buf(new unsigned char[bufsize]); vector vpacket; // string mapped0x20=dns0x20(domain); + uint16_t qid = dns_random(0xffff); DNSPacketWriter pw(vpacket, domain, type); pw.getHeader()->rd=sendRDQuery; - pw.getHeader()->id=dns_random(0xffff); + pw.getHeader()->id=qid; /* RFC 6840 section 5.9: * This document further specifies that validating resolvers SHOULD set * the CD bit on every upstream query. This is regardless of whether @@ -98,20 +137,31 @@ int asyncresolve(const ComboAddress& ip, const DNSName& domain, int type, bool d DTime dt; dt.set(); *now=dt.getTimeval(); + +#ifdef HAVE_PROTOBUF + boost::uuids::uuid uuid; + const struct timeval queryTime = *now; + + if (outgoingLogger) { + uuid = (*t_uuidGenerator)(); + logOutgoingQuery(outgoingLogger, context ? context->d_initialRequestId : boost::none, uuid, ip, domain, type, qid, doTCP, vpacket.size()); + } +#endif + errno=0; if(!doTCP) { int queryfd; if(ip.sin4.sin_family==AF_INET6) g_stats.ipv6queries++; - if((ret=asendto((const char*)&*vpacket.begin(), vpacket.size(), 0, ip, pw.getHeader()->id, + if((ret=asendto((const char*)&*vpacket.begin(), vpacket.size(), 0, ip, qid, domain, type, &queryfd)) < 0) { return ret; // passes back the -2 EMFILE } // sleep until we see an answer to this, interface to mtasker - ret=arecvfrom(reinterpret_cast(buf.get()), bufsize-1,0, ip, &len, pw.getHeader()->id, + ret=arecvfrom(reinterpret_cast(buf.get()), bufsize-1,0, ip, &len, qid, domain, type, queryfd, now); } else { @@ -178,6 +228,11 @@ int asyncresolve(const ComboAddress& ip, const DNSName& domain, int type, bool d lwr->d_rcode=mdp.d_header.rcode; if(mdp.d_header.rcode == RCode::FormErr && mdp.d_qname.empty() && mdp.d_qtype == 0 && mdp.d_qclass == 0) { +#ifdef HAVE_PROTOBUF + if(outgoingLogger) { + logIncomingResponse(outgoingLogger, context ? context->d_initialRequestId : boost::none, uuid, ip, domain, type, qid, doTCP, len, lwr->d_rcode, lwr->d_records, queryTime); + } +#endif return 1; // this is "success", the error is set in lwr->d_rcode } @@ -210,13 +265,23 @@ int asyncresolve(const ComboAddress& ip, const DNSName& domain, int type, bool d } } +#ifdef HAVE_PROTOBUF + if(outgoingLogger) { + logIncomingResponse(outgoingLogger, context ? context->d_initialRequestId : boost::none, uuid, ip, domain, type, qid, doTCP, len, lwr->d_rcode, lwr->d_records, queryTime); + } +#endif return 1; } catch(std::exception &mde) { if(::arg().mustDo("log-common-errors")) L<d_rcode = RCode::FormErr; - g_stats.serverParseError++; + g_stats.serverParseError++; +#ifdef HAVE_PROTOBUF + if(outgoingLogger) { + logIncomingResponse(outgoingLogger, context ? context->d_initialRequestId : boost::none, uuid, ip, domain, type, qid, doTCP, len, lwr->d_rcode, lwr->d_records, queryTime); + } +#endif return 1; // success - oddly enough } catch(...) { diff --git a/pdns/lwres.hh b/pdns/lwres.hh index 0e0fe2263..1762ed98a 100644 --- a/pdns/lwres.hh +++ b/pdns/lwres.hh @@ -40,6 +40,8 @@ #include "pdnsexception.hh" #include "dns.hh" #include "namespaces.hh" +#include "remote_logger.hh" +#include "resolve-context.hh" int asendto(const char *data, size_t len, int flags, const ComboAddress& ip, uint16_t id, const DNSName& domain, uint16_t qtype, int* fd); @@ -65,5 +67,5 @@ public: bool d_haveEDNS{false}; }; -int asyncresolve(const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional& srcmask, LWResult* res); +int asyncresolve(const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional& srcmask, boost::optional context, std::shared_ptr outgoingLogger, LWResult* res); #endif // PDNS_LWRES_HH diff --git a/pdns/pdns_recursor.cc b/pdns/pdns_recursor.cc index 818ecb8b2..b8dd61d7e 100644 --- a/pdns/pdns_recursor.cc +++ b/pdns/pdns_recursor.cc @@ -735,6 +735,9 @@ void startDoResolve(void *p) // Ignore the client-set CD flag pw.getHeader()->cd=0; } +#ifdef HAVE_PROTOBUF + sr.d_initialRequestId = dc->d_uuid; +#endif bool tracedQuery=false; // we could consider letting Lua know about this too bool variableAnswer = false; @@ -996,7 +999,11 @@ void startDoResolve(void *p) L<d_mdp.d_qname<<"|"<d_mdp.d_qtype).getName()<<" for "<d_remote.toStringWithPort()<d_uuid; +#endif + auto state=validateRecords(ctx, ret); if(state == Secure) { if(sr.doLog()) { L<d_mdp.d_qname<<"|"<d_mdp.d_qtype).getName()<<" for "<d_remote.toStringWithPort()<<" validates correctly"<protobufServer) { + if(luaconfsLocal->protobufServer || luaconfsLocal->outgoingProtobufServer) { dc->d_uuid = (*t_uuidGenerator)(); + } + if(luaconfsLocal->protobufServer) { try { const struct dnsheader* dh = (const struct dnsheader*) conn->data; dc->d_ednssubnet = ednssubnet; @@ -1479,7 +1488,9 @@ string* doProcessUDPQuestion(const std::string& question, const ComboAddress& fr boost::uuids::uuid uniqueId; auto luaconfsLocal = g_luaconfs.getLocal(); if (luaconfsLocal->protobufServer) { + uniqueId = (*t_uuidGenerator)(); needECS = true; + } else if (luaconfsLocal->outgoingProtobufServer) { uniqueId = (*t_uuidGenerator)(); } #endif @@ -1602,7 +1613,7 @@ string* doProcessUDPQuestion(const std::string& question, const ComboAddress& fr dc->d_tcp=false; dc->d_policyTags = policyTags; #ifdef HAVE_PROTOBUF - if (luaconfsLocal->protobufServer) { + if (luaconfsLocal->protobufServer || luaconfsLocal->outgoingProtobufServer) { dc->d_uuid = uniqueId; } dc->d_ednssubnet = ednssubnet; @@ -3165,7 +3176,8 @@ int getRootNS(void) { try { res=sr.beginResolve(g_rootdnsname, QType(QType::NS), 1, ret); if (g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate) { - auto state = validateRecords(ret); + ResolveContext ctx; + auto state = validateRecords(ctx, ret); if (state == Bogus) throw PDNSException("Got Bogus validation result for .|NS"); } diff --git a/pdns/protobuf.cc b/pdns/protobuf.cc index e78e22af0..2dfd93010 100644 --- a/pdns/protobuf.cc +++ b/pdns/protobuf.cc @@ -1,15 +1,37 @@ +#include "gettime.hh" +#include "dnsparser.hh" #include "protobuf.hh" #include "dnsparser.hh" #include "gettime.hh" -DNSProtoBufMessage::DNSProtoBufMessage(DNSProtoBufMessageType type) +void DNSProtoBufMessage::setType(DNSProtoBufMessageType type) { #ifdef HAVE_PROTOBUF - d_message.set_type(type == DNSProtoBufMessage::DNSProtoBufMessageType::Query ? PBDNSMessage_Type_DNSQueryType : PBDNSMessage_Type_DNSResponseType); + switch(type) { + case DNSProtoBufMessage::DNSProtoBufMessageType::Query: + d_message.set_type(PBDNSMessage_Type_DNSQueryType); + break; + case DNSProtoBufMessage::DNSProtoBufMessageType::Response: + d_message.set_type(PBDNSMessage_Type_DNSResponseType); + break; + case DNSProtoBufMessage::DNSProtoBufMessageType::OutgoingQuery: + d_message.set_type(PBDNSMessage_Type_DNSOutgoingQueryType); + break; + case DNSProtoBufMessage::DNSProtoBufMessageType::IncomingResponse: + d_message.set_type(PBDNSMessage_Type_DNSIncomingResponseType); + break; + default: + throw std::runtime_error("Unsupported protobuf type: "+std::to_string(type)); + } #endif /* HAVE_PROTOBUF */ } +DNSProtoBufMessage::DNSProtoBufMessage(DNSProtoBufMessageType type) +{ + setType(type); +} + void DNSProtoBufMessage::setQuestion(const DNSName& qname, uint16_t qtype, uint16_t qclass) { #ifdef HAVE_PROTOBUF @@ -204,6 +226,13 @@ void DNSProtoBufMessage::setUUID(const boost::uuids::uuid& uuid) std::copy(uuid.begin(), uuid.end(), messageId->begin()); } +void DNSProtoBufMessage::setInitialRequestID(const boost::uuids::uuid& uuid) +{ + std::string* messageId = d_message.mutable_initialrequestid(); + messageId->resize(uuid.size()); + std::copy(uuid.begin(), uuid.end(), messageId->begin()); +} + void DNSProtoBufMessage::update(const boost::uuids::uuid& uuid, const ComboAddress* requestor, const ComboAddress* responder, bool isTCP, uint16_t id) { struct timespec ts; @@ -213,7 +242,13 @@ void DNSProtoBufMessage::update(const boost::uuids::uuid& uuid, const ComboAddre setUUID(uuid); d_message.set_id(ntohs(id)); - d_message.set_socketfamily((requestor && requestor->sin4.sin_family == AF_INET) ? PBDNSMessage_SocketFamily_INET : PBDNSMessage_SocketFamily_INET6); + if (requestor) { + d_message.set_socketfamily(requestor->sin4.sin_family == AF_INET ? PBDNSMessage_SocketFamily_INET : PBDNSMessage_SocketFamily_INET6); + } + else if (responder) { + d_message.set_socketfamily(responder->sin4.sin_family == AF_INET ? PBDNSMessage_SocketFamily_INET : PBDNSMessage_SocketFamily_INET6); + } + d_message.set_socketprotocol(isTCP ? PBDNSMessage_SocketProtocol_TCP : PBDNSMessage_SocketProtocol_UDP); if (responder) { @@ -225,11 +260,11 @@ void DNSProtoBufMessage::update(const boost::uuids::uuid& uuid, const ComboAddre } -DNSProtoBufMessage::DNSProtoBufMessage(DNSProtoBufMessageType type, const boost::uuids::uuid& uuid, const ComboAddress* requestor, const ComboAddress* to, const DNSName& domain, int qtype, uint16_t qclass, uint16_t qid, bool isTCP, size_t bytes) +DNSProtoBufMessage::DNSProtoBufMessage(DNSProtoBufMessageType type, const boost::uuids::uuid& uuid, const ComboAddress* requestor, const ComboAddress* responder, const DNSName& domain, int qtype, uint16_t qclass, uint16_t qid, bool isTCP, size_t bytes) { - update(uuid, requestor, to, isTCP, qid); + update(uuid, requestor, responder, isTCP, qid); - d_message.set_type(type == DNSProtoBufMessage::DNSProtoBufMessageType::Query ? PBDNSMessage_Type_DNSQueryType : PBDNSMessage_Type_DNSResponseType); + setType(type); setBytes(bytes); setQuestion(domain, qtype, qclass); diff --git a/pdns/protobuf.hh b/pdns/protobuf.hh index 4b972a5f7..b9aeaf5c9 100644 --- a/pdns/protobuf.hh +++ b/pdns/protobuf.hh @@ -40,7 +40,9 @@ class DNSProtoBufMessage public: enum DNSProtoBufMessageType { Query, - Response + Response, + OutgoingQuery, + IncomingResponse }; DNSProtoBufMessage() @@ -53,6 +55,7 @@ public: { } + void setType(DNSProtoBufMessage::DNSProtoBufMessageType type); void setQuestion(const DNSName& qname, uint16_t qtype, uint16_t qclass); void setEDNSSubnet(const Netmask& subnet, uint8_t mask=128); void setBytes(size_t bytes); @@ -71,6 +74,7 @@ public: DNSProtoBufMessage(DNSProtoBufMessage::DNSProtoBufMessageType type, const boost::uuids::uuid& uuid, const ComboAddress* requestor, const ComboAddress* responder, const DNSName& domain, int qtype, uint16_t qclass, uint16_t qid, bool isTCP, size_t bytes); void update(const boost::uuids::uuid& uuid, const ComboAddress* requestor, const ComboAddress* responder, bool isTCP, uint16_t id); void setUUID(const boost::uuids::uuid& uuid); + void setInitialRequestID(const boost::uuids::uuid& uuid); protected: PBDNSMessage d_message; diff --git a/pdns/rec-lua-conf.cc b/pdns/rec-lua-conf.cc index 86050da3b..32afe58f0 100644 --- a/pdns/rec-lua-conf.cc +++ b/pdns/rec-lua-conf.cc @@ -295,6 +295,24 @@ void loadRecursorLuaConfig(const std::string& fname, bool checkOnly) theL()< timeout, const boost::optional maxQueuedEntries, const boost::optional reconnectWaitTime, boost::optional asyncConnect) { + try { + ComboAddress server(server_); + if (!lci.outgoingProtobufServer) { + lci.outgoingProtobufServer = std::make_shared(server, timeout ? *timeout : 2, maxQueuedEntries ? *maxQueuedEntries : 100, reconnectWaitTime ? *reconnectWaitTime : 1, asyncConnect ? *asyncConnect : false); + } + else { + theL()<toString()< dsAnchors; map negAnchors; std::shared_ptr protobufServer{nullptr}; + std::shared_ptr outgoingProtobufServer{nullptr}; uint8_t protobufMaskV4{32}; uint8_t protobufMaskV6{128}; bool protobufTaggedOnly{false}; diff --git a/pdns/recursordist/Makefile.am b/pdns/recursordist/Makefile.am index d034dc96c..24eed453d 100644 --- a/pdns/recursordist/Makefile.am +++ b/pdns/recursordist/Makefile.am @@ -115,6 +115,7 @@ pdns_recursor_SOURCES = \ reczones.cc \ remote_logger.cc remote_logger.hh \ resolver.hh resolver.cc \ + resolve-context.hh \ responsestats.hh responsestats.cc \ root-addresses.hh \ root-dnssec.hh \ diff --git a/pdns/recursordist/resolve-context.hh b/pdns/recursordist/resolve-context.hh new file mode 120000 index 000000000..ad6002f39 --- /dev/null +++ b/pdns/recursordist/resolve-context.hh @@ -0,0 +1 @@ +../resolve-context.hh \ No newline at end of file diff --git a/pdns/resolve-context.hh b/pdns/resolve-context.hh new file mode 100644 index 000000000..c22abcdde --- /dev/null +++ b/pdns/resolve-context.hh @@ -0,0 +1,22 @@ +#pragma once + +#include "config.h" + +#ifdef HAVE_PROTOBUF +#include +#endif + +struct ResolveContext { + ResolveContext() + { + } + ResolveContext(const ResolveContext& ctx) + { +#ifdef HAVE_PROTOBUF + this->d_initialRequestId = ctx.d_initialRequestId; +#endif + } +#ifdef HAVE_PROTOBUF + boost::optional d_initialRequestId; +#endif +}; diff --git a/pdns/secpoll-recursor.cc b/pdns/secpoll-recursor.cc index 426644564..c7fa5b817 100644 --- a/pdns/secpoll-recursor.cc +++ b/pdns/secpoll-recursor.cc @@ -42,8 +42,10 @@ void doSecPoll(time_t* last_secpoll) DNSName query(qstring); int res=sr.beginResolve(query, QType(QType::TXT), 1, ret); - if (g_dnssecmode != DNSSECMode::Off && res) - state = validateRecords(ret); + if (g_dnssecmode != DNSSECMode::Off && res) { + ResolveContext ctx; + state = validateRecords(ctx, ret); + } if(state == Bogus) { L<mode; SyncRes::EDNSStatus::EDNSMode oldmode = mode; int EDNSLevel=0; + auto luaconfsLocal = g_luaconfs.getLocal(); + ResolveContext ctx; +#ifdef HAVE_PROTOBUF + ctx.d_initialRequestId = d_initialRequestId; +#endif int ret; for(int tries = 0; tries < 3; ++tries) { @@ -368,7 +373,7 @@ int SyncRes::asyncresolveWrapper(const ComboAddress& ip, bool ednsMANDATORY, con else if(ednsMANDATORY || mode==EDNSStatus::UNKNOWN || mode==EDNSStatus::EDNSOK || mode==EDNSStatus::EDNSIGNORANT) EDNSLevel = 1; - ret=asyncresolve(ip, domain, type, doTCP, sendRDQuery, EDNSLevel, now, srcmask, res); + ret=asyncresolve(ip, domain, type, doTCP, sendRDQuery, EDNSLevel, now, srcmask, ctx, luaconfsLocal->outgoingProtobufServer, res); if(ret < 0) { return ret; // transport error, nothing to learn here } diff --git a/pdns/syncres.hh b/pdns/syncres.hh index e8520a99f..ef8305ca1 100644 --- a/pdns/syncres.hh +++ b/pdns/syncres.hh @@ -35,6 +35,7 @@ #include #include "misc.hh" #include "lwres.hh" +#include #include #include #include "sstuff.hh" @@ -49,6 +50,12 @@ #include "filterpo.hh" +#include "config.h" +#ifdef HAVE_PROTOBUF +#include +#include +#endif + void primeHints(void); int getRootNS(void); class RecursorLua4; @@ -365,6 +372,9 @@ public: static unsigned int s_maxtotusec; std::unordered_map d_discardedPolicies; DNSFilterEngine::Policy d_appliedPolicy; +#ifdef HAVE_PROTOBUF + boost::optional d_initialRequestId; +#endif unsigned int d_outqueries; unsigned int d_tcpoutqueries; unsigned int d_throttledqueries; @@ -508,7 +518,7 @@ public: private: struct GetBestNSAnswer; int doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype, vector&ret, - int depth, set&beenthere); + int depth, set&beenthere); int doResolve(const DNSName &qname, const QType &qtype, vector&ret, int depth, set& beenthere); bool doOOBResolve(const DNSName &qname, const QType &qtype, vector&ret, int depth, int &res); domainmap_t::const_iterator getBestAuthZone(DNSName* qname); @@ -729,4 +739,8 @@ void parseEDNSSubnetWhitelist(const std::string& wlist); extern __thread struct timeval g_now; +#ifdef HAVE_PROTOBUF +extern __thread boost::uuids::random_generator* t_uuidGenerator; +#endif + #endif diff --git a/pdns/validate-recursor.cc b/pdns/validate-recursor.cc index e6b640644..f6c9372e4 100644 --- a/pdns/validate-recursor.cc +++ b/pdns/validate-recursor.cc @@ -11,12 +11,19 @@ bool g_dnssecLogBogus; class SRRecordOracle : public DNSRecordOracle { public: + SRRecordOracle(const ResolveContext& ctx): d_ctx(ctx) + { + } vector get(const DNSName& qname, uint16_t qtype) override { struct timeval tv; gettimeofday(&tv, 0); SyncRes sr(tv); sr.setId(MT->getTid()); +#ifdef HAVE_PROTOBUF + sr.d_initialRequestId = d_ctx.d_initialRequestId; +#endif + vector ret; sr.d_doDNSSEC=true; if (qtype == QType::DS || qtype == QType::DNSKEY || qtype == QType::NS) @@ -25,6 +32,7 @@ public: d_queries += sr.d_outqueries; return ret; } + const ResolveContext& d_ctx; int d_queries{0}; }; @@ -66,7 +74,7 @@ inline void processNewState(vState& currentState, const vState& newState, bool& hadNTA = true; } -vState validateRecords(const vector& recs) +vState validateRecords(const ResolveContext& ctx, const vector& recs) { if(recs.empty()) return Insecure; // can't secure nothing @@ -84,7 +92,7 @@ vState validateRecords(const vector& recs) set keys; cspmap_t validrrsets; - SRRecordOracle sro; + SRRecordOracle sro(ctx); vState state=Insecure; bool hadNTA = false; diff --git a/pdns/validate-recursor.hh b/pdns/validate-recursor.hh index bf99d7de0..ff261091e 100644 --- a/pdns/validate-recursor.hh +++ b/pdns/validate-recursor.hh @@ -24,8 +24,9 @@ #include "namespaces.hh" #include "validate.hh" #include "logger.hh" +#include "resolve-context.hh" -vState validateRecords(const vector& recs); +vState validateRecords(const ResolveContext& ctx, const vector& recs); /* Off: 3.x behaviour, we do no DNSSEC, no EDNS ProcessNoValidate: we gather DNSSEC records on all queries, but we will never validate -- 2.40.0