From: Remi Gacogne Date: Mon, 16 Apr 2018 16:58:00 +0000 (+0200) Subject: rec: Add seedFile to load RPZ zones from a file, then update via IXFR X-Git-Tag: dnsdist-1.3.1~139^2~2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a66c5cfa2ababf432efa9d59a9868cf5c0800db0;p=pdns rec: Add seedFile to load RPZ zones from a file, then update via IXFR --- diff --git a/pdns/rec-lua-conf.cc b/pdns/rec-lua-conf.cc index 5f8d1d2eb..65a63f94d 100644 --- a/pdns/rec-lua-conf.cc +++ b/pdns/rec-lua-conf.cc @@ -149,44 +149,69 @@ void loadRecursorLuaConfig(const std::string& fname, bool checkOnly) ComboAddress localAddress; ComboAddress master(master_, 53); size_t zoneIdx; + std::shared_ptr sr = nullptr; try { + std::string seedFile; std::string polName(zoneName); - if(options) { + + if (options) { auto& have = *options; size_t zoneSizeHint = 0; parseRPZParameters(have, polName, defpol, maxTTL, zoneSizeHint); if (zoneSizeHint > 0) { zone->reserve(zoneSizeHint); } + if(have.count("tsigname")) { tt.name=DNSName(toLower(boost::get(constGet(have, "tsigname")))); tt.algo=DNSName(toLower(boost::get(constGet(have, "tsigalgo")))); if(B64Decode(boost::get(constGet(have, "tsigsecret")), tt.secret)) throw std::runtime_error("TSIG secret is not valid Base-64 encoded"); } + if(have.count("refresh")) { refresh = boost::get(constGet(have,"refresh")); } + if(have.count("maxReceivedMBytes")) { maxReceivedXFRMBytes = static_cast(boost::get(constGet(have,"maxReceivedMBytes"))); } + if(have.count("localAddress")) { localAddress = ComboAddress(boost::get(constGet(have,"localAddress"))); } + if(have.count("axfrTimeout")) { axfrTimeout = static_cast(boost::get(constGet(have, "axfrTimeout"))); } + + if(have.count("seedFile")) { + seedFile = boost::get(constGet(have, "seedFile")); + } } + if (localAddress != ComboAddress() && localAddress.sin4.sin_family != master.sin4.sin_family) { // We were passed a localAddress, check if its AF matches the master's throw PDNSException("Master address("+master.toString()+") is not of the same Address Family as the local address ("+localAddress.toString()+")."); } - zone->setDomain(DNSName(zoneName)); + DNSName domain(zoneName); + zone->setDomain(domain); zone->setName(polName); zone->setRefresh(refresh); zoneIdx = lci.dfe.addZone(zone); + + if (!seedFile.empty()) { + sr = loadRPZFromFile(seedFile, zone, defpol, maxTTL); + if (zone->getDomain() != domain) { + throw PDNSException("The RPZ zone " + zoneName + " loaded from the seed file (" + zone->getDomain().toString() + ") does not match the one passed in parameter (" + domain.toString() + ")"); + } + + if (sr == nullptr) { + throw PDNSException("The RPZ zone " + zoneName + " loaded from the seed file (" + zone->getDomain().toString() + ") has no SOA record"); + } + } } catch(const std::exception& e) { g_log< loadRPZFromServer(const ComboAddress& master, const } // this function is silent - you do the logging -void loadRPZFromFile(const std::string& fname, std::shared_ptr zone, boost::optional defpol, uint32_t maxTTL) +std::shared_ptr loadRPZFromFile(const std::string& fname, std::shared_ptr zone, boost::optional defpol, uint32_t maxTTL) { + shared_ptr sr = nullptr; ZoneParserTNG zpt(fname); DNSResourceRecord drr; DNSName domain; @@ -233,6 +234,7 @@ void loadRPZFromFile(const std::string& fname, std::shared_ptr(dr); domain = dr.d_name; zone->setDomain(domain); } @@ -248,6 +250,8 @@ void loadRPZFromFile(const std::string& fname, std::shared_ptr > s_rpzStats; @@ -283,14 +287,16 @@ static void setRPZZoneNewState(const std::string& zone, uint32_t serial, uint64_ stats->d_numberOfRecords = numberOfRecords; } -void RPZIXFRTracker(const ComboAddress& master, boost::optional defpol, uint32_t maxTTL, size_t zoneIdx, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, std::shared_ptr zone, const uint16_t axfrTimeout, uint64_t configGeneration) +void RPZIXFRTracker(const ComboAddress& master, boost::optional defpol, uint32_t maxTTL, size_t zoneIdx, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, std::shared_ptr zone, const uint16_t axfrTimeout, std::shared_ptr sr, uint64_t configGeneration) { + bool isPreloaded = sr != nullptr; uint32_t refresh = zone->getRefresh(); DNSName zoneName = zone->getDomain(); std::string polName = zone->getName() ? *(zone->getName()) : zoneName.toString(); - shared_ptr sr; while (!sr) { + /* if we received an empty sr, the zone was not really preloaded */ + try { sr=loadRPZFromServer(master, zoneName, zone, defpol, maxTTL, tt, maxReceivedBytes, localAddress, axfrTimeout); if(refresh == 0) { @@ -318,12 +324,18 @@ void RPZIXFRTracker(const ComboAddress& master, boost::optionalgeneration != configGeneration) { /* the configuration has been reloaded, meaning that a new thread diff --git a/pdns/rpzloader.hh b/pdns/rpzloader.hh index 465bc8765..347084fef 100644 --- a/pdns/rpzloader.hh +++ b/pdns/rpzloader.hh @@ -26,10 +26,10 @@ extern bool g_logRPZChanges; -void loadRPZFromFile(const std::string& fname, std::shared_ptr zone, boost::optional defpol, uint32_t maxTTL); +std::shared_ptr loadRPZFromFile(const std::string& fname, std::shared_ptr zone, boost::optional defpol, uint32_t maxTTL); std::shared_ptr loadRPZFromServer(const ComboAddress& master, const DNSName& zoneName, std::shared_ptr zone, boost::optional defpol, uint32_t maxTTL, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, const uint16_t axfrTimeout); void RPZRecordToPolicy(const DNSRecord& dr, std::shared_ptr zone, bool addOrRemove, boost::optional defpol, uint32_t maxTTL); -void RPZIXFRTracker(const ComboAddress& master, boost::optional defpol, uint32_t maxTTL, size_t polZone, const TSIGTriplet &tt, size_t maxReceivedBytes, const ComboAddress& localAddress, std::shared_ptr zone, uint16_t axfrTimeout, uint64_t configGeneration); +void RPZIXFRTracker(const ComboAddress& master, boost::optional defpol, uint32_t maxTTL, size_t zoneIdx, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, std::shared_ptr zone, const uint16_t axfrTimeout, shared_ptr sr, uint64_t configGeneration); struct rpzStats {