]> granicus.if.org Git - pdns/commitdiff
rec: Add seedFile to load RPZ zones from a file, then update via IXFR
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 16 Apr 2018 16:58:00 +0000 (18:58 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 18 Apr 2018 08:45:24 +0000 (10:45 +0200)
pdns/rec-lua-conf.cc
pdns/rpzloader.cc
pdns/rpzloader.hh

index 5f8d1d2eb9edc258933b27dd97864767843b99fc..65a63f94d01d42a820701ad63b45ed849198d529 100644 (file)
@@ -149,44 +149,69 @@ void loadRecursorLuaConfig(const std::string& fname, bool checkOnly)
       ComboAddress localAddress;
       ComboAddress master(master_, 53);
       size_t zoneIdx;
+      std::shared_ptr<SOARecordContent> 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<string>(constGet(have, "tsigname"))));
             tt.algo=DNSName(toLower(boost::get<string>(constGet(have, "tsigalgo"))));
             if(B64Decode(boost::get<string>(constGet(have, "tsigsecret")), tt.secret))
               throw std::runtime_error("TSIG secret is not valid Base-64 encoded");
           }
+
           if(have.count("refresh")) {
             refresh = boost::get<uint32_t>(constGet(have,"refresh"));
           }
+
           if(have.count("maxReceivedMBytes")) {
             maxReceivedXFRMBytes = static_cast<size_t>(boost::get<uint32_t>(constGet(have,"maxReceivedMBytes")));
           }
+
           if(have.count("localAddress")) {
             localAddress = ComboAddress(boost::get<string>(constGet(have,"localAddress")));
           }
+
           if(have.count("axfrTimeout")) {
             axfrTimeout = static_cast<uint16_t>(boost::get<uint32_t>(constGet(have, "axfrTimeout")));
           }
+
+          if(have.count("seedFile")) {
+            seedFile = boost::get<std::string>(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<<Logger::Error<<"Problem configuring 'rpzMaster': "<<e.what()<<endl;
@@ -199,7 +224,7 @@ void loadRecursorLuaConfig(const std::string& fname, bool checkOnly)
 
       try {
           if (!checkOnly) {
-            std::thread t(RPZIXFRTracker, master, defpol, maxTTL, zoneIdx, tt, maxReceivedXFRMBytes * 1024 * 1024, localAddress, zone, axfrTimeout, lci.generation);
+            std::thread t(RPZIXFRTracker, master, defpol, maxTTL, zoneIdx, tt, maxReceivedXFRMBytes * 1024 * 1024, localAddress, zone, axfrTimeout, sr, lci.generation);
             t.detach();
           }
       }
index 79aa90dd71e0f83abe880cfe802478a7de823208..73a6dae3d8e6c51893f07957e5cf1439b29d4a78 100644 (file)
@@ -222,8 +222,9 @@ shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const
 }
 
 // this function is silent - you do the logging
-void loadRPZFromFile(const std::string& fname, std::shared_ptr<DNSFilterEngine::Zone> zone, boost::optional<DNSFilterEngine::Policy> defpol, uint32_t maxTTL)
+std::shared_ptr<SOARecordContent> loadRPZFromFile(const std::string& fname, std::shared_ptr<DNSFilterEngine::Zone> zone, boost::optional<DNSFilterEngine::Policy> defpol, uint32_t maxTTL)
 {
+  shared_ptr<SOARecordContent> sr = nullptr;
   ZoneParserTNG zpt(fname);
   DNSResourceRecord drr;
   DNSName domain;
@@ -233,6 +234,7 @@ void loadRPZFromFile(const std::string& fname, std::shared_ptr<DNSFilterEngine::
        drr.content=".";
       DNSRecord dr(drr);
       if(dr.d_type == QType::SOA) {
+        sr = getRR<SOARecordContent>(dr);
         domain = dr.d_name;
         zone->setDomain(domain);
       }
@@ -248,6 +250,8 @@ void loadRPZFromFile(const std::string& fname, std::shared_ptr<DNSFilterEngine::
       throw PDNSException("Issue parsing '"+drr.qname.toLogString()+"' '"+drr.content+"' at "+zpt.getLineOfFile()+": "+pe.reason);
     }
   }
+
+  return sr;
 }
 
 static std::unordered_map<std::string, shared_ptr<rpzStats> > 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<DNSFilterEngine::Policy> defpol, uint32_t maxTTL, size_t zoneIdx, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, std::shared_ptr<DNSFilterEngine::Zone> zone, const uint16_t axfrTimeout, uint64_t configGeneration)
+void RPZIXFRTracker(const ComboAddress& master, boost::optional<DNSFilterEngine::Policy> defpol, uint32_t maxTTL, size_t zoneIdx, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, std::shared_ptr<DNSFilterEngine::Zone> zone, const uint16_t axfrTimeout, std::shared_ptr<SOARecordContent> 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<SOARecordContent> 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::optional<DNSFilterEngine:
   }
 
   auto luaconfsLocal = g_luaconfs.getLocal();
+  bool skipRefreshDelay = isPreloaded;
 
   for(;;) {
     DNSRecord dr;
     dr.d_content=sr;
 
-    sleep(refresh);
+    if (skipRefreshDelay) {
+      skipRefreshDelay = false;
+    }
+    else {
+      sleep(refresh);
+    }
 
     if (luaconfsLocal->generation != configGeneration) {
       /* the configuration has been reloaded, meaning that a new thread
index 465bc876573592bf15c6f52e0e40acb7b56f8911..347084fef1a69e2f7d1b622e41409a807231c785 100644 (file)
 
 extern bool g_logRPZChanges;
 
-void loadRPZFromFile(const std::string& fname, std::shared_ptr<DNSFilterEngine::Zone> zone, boost::optional<DNSFilterEngine::Policy> defpol, uint32_t maxTTL);
+std::shared_ptr<SOARecordContent> loadRPZFromFile(const std::string& fname, std::shared_ptr<DNSFilterEngine::Zone> zone, boost::optional<DNSFilterEngine::Policy> defpol, uint32_t maxTTL);
 std::shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const DNSName& zoneName, std::shared_ptr<DNSFilterEngine::Zone> zone, boost::optional<DNSFilterEngine::Policy> 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<DNSFilterEngine::Zone> zone, bool addOrRemove, boost::optional<DNSFilterEngine::Policy> defpol, uint32_t maxTTL);
-void RPZIXFRTracker(const ComboAddress& master, boost::optional<DNSFilterEngine::Policy> defpol, uint32_t maxTTL, size_t polZone, const TSIGTriplet &tt, size_t maxReceivedBytes, const ComboAddress& localAddress, std::shared_ptr<DNSFilterEngine::Zone> zone, uint16_t axfrTimeout, uint64_t configGeneration);
+void RPZIXFRTracker(const ComboAddress& master, boost::optional<DNSFilterEngine::Policy> defpol, uint32_t maxTTL, size_t zoneIdx, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, std::shared_ptr<DNSFilterEngine::Zone> zone, const uint16_t axfrTimeout, shared_ptr<SOARecordContent> sr, uint64_t configGeneration);
 
 struct rpzStats
 {