From: Remi Gacogne Date: Fri, 4 Nov 2016 16:28:22 +0000 (+0100) Subject: rec: Log outgoing queries / incoming responses via protobuf X-Git-Tag: rec-4.0.5-rc1~27^2~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7a2a645db683f1ea75a2416b6a1dcc4233e1731c;p=pdns rec: Log outgoing queries / incoming responses via protobuf (cherry picked from commit 4898a34807043c2af442ef983f9ef45e0b473651) --- 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 9e67c4efa..65064058d 100644 --- a/docs/markdown/recursor/settings.md +++ b/docs/markdown/recursor/settings.md @@ -544,6 +544,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 931da94ab..f3c1f23fc 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 0443ff9b7..b24ac28d2 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; @@ -983,7 +986,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; @@ -1455,7 +1464,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 @@ -1576,7 +1587,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; @@ -3140,7 +3151,8 @@ int getRootNS(void) { try { res=sr.beginResolve(DNSName("."), 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 6d8189c15..1b91ad85a 100644 --- a/pdns/rec-lua-conf.cc +++ b/pdns/rec-lua-conf.cc @@ -287,6 +287,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}; }; diff --git a/pdns/recursordist/Makefile.am b/pdns/recursordist/Makefile.am index 0ee02e579..3b8b402d2 100644 --- a/pdns/recursordist/Makefile.am +++ b/pdns/recursordist/Makefile.am @@ -116,6 +116,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) { @@ -369,7 +374,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 a1151b116..698c73b8e 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; @@ -366,6 +373,9 @@ public: static unsigned int s_maxdepth; 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; @@ -730,4 +740,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 12a9984d6..799ed0536 100644 --- a/pdns/validate-recursor.cc +++ b/pdns/validate-recursor.cc @@ -11,11 +11,18 @@ 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; @@ -25,6 +32,7 @@ public: d_queries += sr.d_outqueries; return ret; } + const ResolveContext& d_ctx; int d_queries{0}; }; @@ -53,7 +61,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 @@ -71,7 +79,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 5604ac533..63b891d0e 100644 --- a/pdns/validate-recursor.hh +++ b/pdns/validate-recursor.hh @@ -23,8 +23,9 @@ #include "dnsparser.hh" #include "namespaces.hh" #include "validate.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