]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
rec: Use the RPZ zone's TTL and add a new `maxTTL` setting
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 20 Feb 2017 08:07:43 +0000 (09:07 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 21 Feb 2017 09:33:18 +0000 (10:33 +0100)
docs/markdown/recursor/settings.md
pdns/filterpo.hh
pdns/rec-lua-conf.cc
pdns/reczones.cc
pdns/rpzloader.cc
pdns/rpzloader.hh

index 99ab17631e35fd5910961213dce7724bf7ee22c2..46aff0043acb80a272949e6d5b24b3e051b034db 100644 (file)
@@ -504,9 +504,10 @@ In this example, 'policy.rpz' denotes the name of the zone to query for.
 
 Settings for `rpzFile` and `rpzMaster` can contain:
 
-* defpol = Policy.Custom, Policy.Drop, Policy.NXDOMAIN, Policy.NODATA, Policy.Truncate, Policy.NoAction
+* defpol = Default policy: Policy.Custom, Policy.Drop, Policy.NXDOMAIN, Policy.NODATA, Policy.Truncate, Policy.NoAction
 * defcontent = CNAME field to return in case of defpol=Policy.Custom
-* defttl = the TTL of the CNAME field to be synthesized. The default is to use the zone's TTL
+* defttl = the TTL of the CNAME field to be synthesized for the default policy. The default is to use the zone's TTL
+* maxTTL = the maximum TTL value of the synthesized records, overriding a higher value from `defttl` or the zone. Default is unlimited
 * policyName = the name logged as 'appliedPolicy' in protobuf messages when this policy is applied
 * zoneSizeHint = an indication of the number of expected entries in the zone, speeding up the loading of huge zones by reserving space in advance
 
index 018cb7d77f1db004cc17377b5ea361502e2e43df..fb9ee4c1c44c1379bc5ba25f613ab6875ab3319a 100644 (file)
@@ -77,7 +77,7 @@ public:
     PolicyKind d_kind;
     std::shared_ptr<DNSRecordContent> d_custom;
     std::shared_ptr<std::string> d_name;
-    int d_ttl;
+    int32_t d_ttl;
   };
 
   DNSFilterEngine();
index f06575bd57763c71517342dd6b5fa08884d647bf..1f90d94f3ebfc2d9a9fb90cdbfd22f9c98404a86 100644 (file)
@@ -60,6 +60,37 @@ void loadRecursorLuaConfig(const std::string& fname, bool checkOnly)
 }
 #else
 
+static void parseRPZParameters(const std::unordered_map<string,boost::variant<uint32_t, string> >& have, std::string& polName, boost::optional<DNSFilterEngine::Policy>& defpol, uint32_t& maxTTL, size_t& zoneSizeHint)
+{
+  if(have.count("policyName")) {
+    polName = boost::get<std::string>(constGet(have, "policyName"));
+  }
+  if(have.count("defpol")) {
+    defpol=DNSFilterEngine::Policy();
+    defpol->d_kind = (DNSFilterEngine::PolicyKind)boost::get<uint32_t>(constGet(have, "defpol"));
+    defpol->d_name = std::make_shared<std::string>(polName);
+    if(defpol->d_kind == DNSFilterEngine::PolicyKind::Custom) {
+      defpol->d_custom=
+        shared_ptr<DNSRecordContent>(
+          DNSRecordContent::mastermake(QType::CNAME, 1,
+                                       boost::get<string>(constGet(have,"defcontent"))
+            )
+          );
+
+      if(have.count("defttl"))
+        defpol->d_ttl = static_cast<int32_t>(boost::get<uint32_t>(constGet(have, "defttl")));
+      else
+        defpol->d_ttl = -1; // get it from the zone
+    }
+  }
+  if(have.count("maxTTL")) {
+    maxTTL = boost::get<uint32_t>(constGet(have, "maxTTL"));
+  }
+  if(have.count("zoneSizeHint")) {
+    zoneSizeHint = static_cast<size_t>(boost::get<uint32_t>(constGet(have, "zoneSizeHint")));
+  }
+}
+
 void loadRecursorLuaConfig(const std::string& fname, bool checkOnly)
 {
   LuaConfigItems lci;
@@ -89,41 +120,23 @@ void loadRecursorLuaConfig(const std::string& fname, bool checkOnly)
   };
   Lua.writeVariable("Policy", pmap);
 
-  Lua.writeFunction("rpzFile", [&lci](const string& filename, const boost::optional<std::unordered_map<string,boost::variant<int, string>>>& options) {
+  Lua.writeFunction("rpzFile", [&lci](const string& filename, const boost::optional<std::unordered_map<string,boost::variant<uint32_t, string>>>& options) {
       try {
        boost::optional<DNSFilterEngine::Policy> defpol;
        std::string polName("rpzFile");
        const size_t zoneIdx = lci.dfe.size();
+       uint32_t maxTTL = std::numeric_limits<uint32_t>::max();
        if(options) {
          auto& have = *options;
-         if(have.count("policyName")) {
-           polName = boost::get<std::string>(constGet(have, "policyName"));
-         }
-         if(have.count("defpol")) {
-           defpol=DNSFilterEngine::Policy();
-           defpol->d_kind = (DNSFilterEngine::PolicyKind)boost::get<int>(constGet(have, "defpol"));
-           defpol->d_name = std::make_shared<std::string>(polName);
-           if(defpol->d_kind == DNSFilterEngine::PolicyKind::Custom) {
-             defpol->d_custom=
-               shared_ptr<DNSRecordContent>(
-                                            DNSRecordContent::mastermake(QType::CNAME, 1, 
-                                                                         boost::get<string>(constGet(have,"defcontent"))
-                                                                         )
-                                            );
-        
-             if(have.count("defttl"))
-               defpol->d_ttl = boost::get<int>(constGet(have, "defttl"));
-             else
-               defpol->d_ttl = -1; // get it from the zone
-           }
-         }
-          if(have.count("zoneSizeHint")) {
-            lci.dfe.reserve(zoneIdx, static_cast<size_t>(boost::get<int>(constGet(have, "zoneSizeHint"))));
+          size_t zoneSizeHint = 0;
+          parseRPZParameters(have, polName, defpol, maxTTL, zoneSizeHint);
+          if (zoneSizeHint > 0) {
+            lci.dfe.reserve(zoneIdx, zoneSizeHint);
           }
        }
         theL()<<Logger::Warning<<"Loading RPZ from file '"<<filename<<"'"<<endl;
         lci.dfe.setPolicyName(zoneIdx, polName);
-        loadRPZFromFile(filename, lci.dfe, defpol, zoneIdx);
+        loadRPZFromFile(filename, lci.dfe, defpol, maxTTL, zoneIdx);
         theL()<<Logger::Warning<<"Done loading RPZ from file '"<<filename<<"'"<<endl;
       }
       catch(std::exception& e) {
@@ -132,41 +145,22 @@ void loadRecursorLuaConfig(const std::string& fname, bool checkOnly)
     });
 
 
-  Lua.writeFunction("rpzMaster", [&lci, checkOnly](const string& master_, const string& zone_, const boost::optional<std::unordered_map<string,boost::variant<int, string>>>& options) {
+  Lua.writeFunction("rpzMaster", [&lci, checkOnly](const string& master_, const string& zone_, const boost::optional<std::unordered_map<string,boost::variant<uint32_t, string>>>& options) {
       try {
        boost::optional<DNSFilterEngine::Policy> defpol;
         TSIGTriplet tt;
-        int refresh=0;
-       std::string polName;
+        uint32_t refresh=0;
+       std::string polName(zone_);
        size_t maxReceivedXFRMBytes = 0;
+       uint32_t maxTTL = std::numeric_limits<uint32_t>::max();
        ComboAddress localAddress;
        const size_t zoneIdx = lci.dfe.size();
        if(options) {
          auto& have = *options;
-          polName = zone_;
-         if(have.count("policyName"))
-           polName = boost::get<std::string>(constGet(have, "policyName"));
-         if(have.count("defpol")) {
-           //      cout<<"Set a default policy"<<endl;
-           defpol=DNSFilterEngine::Policy();
-           defpol->d_kind = (DNSFilterEngine::PolicyKind)boost::get<int>(constGet(have, "defpol"));
-           defpol->d_name = std::make_shared<std::string>(polName);
-           if(defpol->d_kind == DNSFilterEngine::PolicyKind::Custom) {
-             //              cout<<"Setting a custom field even!"<<endl;
-             defpol->d_custom=
-               shared_ptr<DNSRecordContent>(
-                                            DNSRecordContent::mastermake(QType::CNAME, 1, 
-                                                                         boost::get<string>(constGet(have,"defcontent"))
-                                                                         )
-                                            );
-             if(have.count("defttl"))
-               defpol->d_ttl = boost::get<int>(constGet(have, "defttl"));
-             else
-               defpol->d_ttl = -1; // get it from the zone
-           }
-         }
-          if(have.count("zoneSizeHint")) {
-            lci.dfe.reserve(zoneIdx, static_cast<size_t>(boost::get<int>(constGet(have, "zoneSizeHint"))));
+          size_t zoneSizeHint = 0;
+          parseRPZParameters(have, polName, defpol, maxTTL, zoneSizeHint);
+          if (zoneSizeHint > 0) {
+            lci.dfe.reserve(zoneIdx, zoneSizeHint);
           }
          if(have.count("tsigname")) {
             tt.name=DNSName(toLower(boost::get<string>(constGet(have, "tsigname"))));
@@ -175,10 +169,10 @@ void loadRecursorLuaConfig(const std::string& fname, bool checkOnly)
               throw std::runtime_error("TSIG secret is not valid Base-64 encoded");
           }
           if(have.count("refresh")) {
-            refresh = boost::get<int>(constGet(have,"refresh"));
+            refresh = boost::get<uint32_t>(constGet(have,"refresh"));
           }
           if(have.count("maxReceivedMBytes")) {
-            maxReceivedXFRMBytes = static_cast<size_t>(boost::get<int>(constGet(have,"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")));
@@ -192,10 +186,10 @@ void loadRecursorLuaConfig(const std::string& fname, bool checkOnly)
         lci.dfe.setPolicyName(zoneIdx, polName);
 
         if (!checkOnly) {
-          auto sr=loadRPZFromServer(master, zone, lci.dfe, defpol, zoneIdx, tt, maxReceivedXFRMBytes * 1024 * 1024, localAddress);
+          auto sr=loadRPZFromServer(master, zone, lci.dfe, defpol, maxTTL, zoneIdx, tt, maxReceivedXFRMBytes * 1024 * 1024, localAddress);
           if(refresh)
             sr->d_st.refresh=refresh;
-          std::thread t(RPZIXFRTracker, master, zone, defpol, zoneIdx, tt, sr, maxReceivedXFRMBytes * 1024 * 1024, localAddress);
+          std::thread t(RPZIXFRTracker, master, zone, defpol, maxTTL, zoneIdx, tt, sr, maxReceivedXFRMBytes * 1024 * 1024, localAddress);
           t.detach();
         }
       }
index 7d9a4f5653262c93ec9f111e40a2cd0a72a1e774..d319c4663f434770023f7b59bb6cf5b695419087 100644 (file)
@@ -310,9 +310,9 @@ string reloadAuthAndForwards()
 }
 
 
-void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, boost::optional<DNSFilterEngine::Policy> defpol, size_t polZone, const TSIGTriplet& tt, shared_ptr<SOARecordContent> oursr, size_t maxReceivedBytes, const ComboAddress& localAddress)
+void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, boost::optional<DNSFilterEngine::Policy> defpol, uint32_t maxTTL, size_t polZone, const TSIGTriplet& tt, shared_ptr<SOARecordContent> oursr, size_t maxReceivedBytes, const ComboAddress& localAddress)
 {
-  int refresh = oursr->d_st.refresh;
+  uint32_t refresh = oursr->d_st.refresh;
   for(;;) {
     DNSRecord dr;
     dr.d_content=oursr;
@@ -359,7 +359,7 @@ void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, boost::opti
        else {
           totremove++;
          L<<Logger::Debug<<"Had removal of "<<rr.d_name<<endl;
-         RPZRecordToPolicy(rr, luaconfsCopy.dfe, false, defpol, polZone);
+         RPZRecordToPolicy(rr, luaconfsCopy.dfe, false, defpol, maxTTL, polZone);
        }
       }
 
@@ -376,7 +376,7 @@ void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, boost::opti
        else {
           totadd++;
          L<<Logger::Debug<<"Had addition of "<<rr.d_name<<endl;
-         RPZRecordToPolicy(rr, luaconfsCopy.dfe, true, defpol, polZone);
+         RPZRecordToPolicy(rr, luaconfsCopy.dfe, true, defpol, maxTTL, polZone);
        }
       }
     }
index 8078b8759f338e5fe35711541247fdb7daf27c5b..cbda6e05ccd428af00dca0c18bf025bc733b92f4 100644 (file)
@@ -58,7 +58,7 @@ static Netmask makeNetmaskFromRPZ(const DNSName& name)
   return Netmask(v6);
 }
 
-void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, bool addOrRemove, boost::optional<DNSFilterEngine::Policy> defpol, size_t place)
+void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, bool addOrRemove, boost::optional<DNSFilterEngine::Policy> defpol, uint32_t maxTTL, size_t place)
 {
   static const DNSName drop("rpz-drop."), truncate("rpz-tcp-only."), noaction("rpz-passthru.");
   static const DNSName rpzClientIP("rpz-client-ip"), rpzIP("rpz-ip"),
@@ -115,8 +115,11 @@ void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, bool addOrR
     }
   }
 
-  if(pol.d_ttl < 0)
-    pol.d_ttl = dr.d_ttl;
+  if (!defpol || defpol->d_ttl < 0) {
+    pol.d_ttl = static_cast<int32_t>(std::min(maxTTL, dr.d_ttl));
+  } else {
+    pol.d_ttl = static_cast<int32_t>(std::min(maxTTL, static_cast<uint32_t>(pol.d_ttl)));
+  }
 
   // now to DO something with that
   
@@ -157,7 +160,7 @@ void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, bool addOrR
   }
 }
 
-shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const DNSName& zone, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, size_t place, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress)
+shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const DNSName& zone, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, uint32_t maxTTL, size_t place, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress)
 {
   L<<Logger::Warning<<"Loading RPZ zone '"<<zone<<"' from "<<master.toStringWithPort()<<endl;
   if(!tt.name.empty())
@@ -185,7 +188,7 @@ shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const
        continue;
       }
 
-      RPZRecordToPolicy(dr, target, true, defpol, place);
+      RPZRecordToPolicy(dr, target, true, defpol, maxTTL, place);
       nrecords++;
     } 
     if(last != time(0)) {
@@ -198,7 +201,7 @@ shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const
 }
 
 // this function is silent - you do the logging
-int loadRPZFromFile(const std::string& fname, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, size_t place)
+int loadRPZFromFile(const std::string& fname, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, uint32_t maxTTL, size_t place)
 {
   ZoneParserTNG zpt(fname);
   DNSResourceRecord drr;
@@ -216,7 +219,7 @@ int loadRPZFromFile(const std::string& fname, DNSFilterEngine& target, boost::op
       }
       else {
        dr.d_name=dr.d_name.makeRelative(domain);
-       RPZRecordToPolicy(dr, target, true, defpol, place);
+       RPZRecordToPolicy(dr, target, true, defpol, maxTTL, place);
       }
     }
     catch(PDNSException& pe) {
index eebbeb2d578f19fa98afbc71179fed952399da06..6026361bb9404be2b14e40fc569df5141086e6fb 100644 (file)
@@ -24,7 +24,7 @@
 #include <string>
 #include "dnsrecords.hh"
 
-int loadRPZFromFile(const std::string& fname, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, size_t place);
-std::shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const DNSName& zone, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, size_t place, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress);
-void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, bool addOrRemove, boost::optional<DNSFilterEngine::Policy> defpol, size_t place);
-void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, boost::optional<DNSFilterEngine::Policy> defpol, size_t polZone, const TSIGTriplet &tt, shared_ptr<SOARecordContent> oursr, size_t maxReceivedBytes, const ComboAddress& localAddress);
+int loadRPZFromFile(const std::string& fname, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, uint32_t maxTTL, size_t place);
+std::shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const DNSName& zone, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, uint32_t maxTTL, size_t place, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress);
+void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, bool addOrRemove, boost::optional<DNSFilterEngine::Policy> defpol, uint32_t maxTTL, size_t place);
+void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, boost::optional<DNSFilterEngine::Policy> defpol, uint32_t maxTTL, size_t polZone, const TSIGTriplet &tt, shared_ptr<SOARecordContent> oursr, size_t maxReceivedBytes, const ComboAddress& localAddress);