]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
add default/override policies to RPZ, move RPZ config to the Lua configuration file...
authorbert hubert <bert.hubert@netherlabs.nl>
Tue, 1 Dec 2015 16:42:15 +0000 (17:42 +0100)
committerbert hubert <bert.hubert@netherlabs.nl>
Tue, 1 Dec 2015 16:42:15 +0000 (17:42 +0100)
pdns/pdns_recursor.cc
pdns/rec-lua-conf.cc
pdns/rec-lua-conf.hh
pdns/reczones.cc
pdns/rpzloader.cc
pdns/rpzloader.hh
pdns/syncres.cc
pdns/syncres.hh

index 8f063f28bd1748e2f06a47f8bb457dbe1e50e23c..261dbc5109ce6d7f302d80024e1b5bb31a875ba6 100644 (file)
@@ -105,8 +105,6 @@ __thread shared_ptr<Regex>* t_traceRegex;
 NetmaskGroup g_ednssubnets;
 SuffixMatchNode g_ednsdomains;
 
-DNSFilterEngine g_dfe;
-
 RecursorControlChannel s_rcc; // only active in thread 0
 
 // for communicating with our threads
@@ -611,6 +609,8 @@ void startDoResolve(void *p)
     vector<DNSRecord> ret;
     vector<uint8_t> packet;
 
+    auto luaconfsLocal = g_luaconfs.getLocal();
+
     DNSPacketWriter pw(packet, dc->d_mdp.d_qname, dc->d_mdp.d_qtype, dc->d_mdp.d_qclass);
 
     pw.getHeader()->aa=0;
@@ -672,7 +672,7 @@ void startDoResolve(void *p)
 
     // if there is a RecursorLua active, and it 'took' the query in preResolve, we don't launch beginResolve
 
-    dfepol = g_dfe.getQueryPolicy(dc->d_mdp.d_qname, dc->d_remote);
+    dfepol = luaconfsLocal->dfe.getQueryPolicy(dc->d_mdp.d_qname, dc->d_remote);
 
     switch(dfepol.d_kind) {
     case DNSFilterEngine::PolicyKind::NoAction:
@@ -721,7 +721,7 @@ void startDoResolve(void *p)
         res = RCode::ServFail;
       }
 
-      dfepol = g_dfe.getPostPolicy(ret); 
+      dfepol = luaconfsLocal->dfe.getPostPolicy(ret); 
       switch(dfepol.d_kind) {
       case DNSFilterEngine::PolicyKind::NoAction:
        break;
@@ -750,6 +750,7 @@ void startDoResolve(void *p)
        break;
 
       case DNSFilterEngine::PolicyKind::Custom:
+       ret.clear();
        res=RCode::NoError;
        spoofed.d_name=dc->d_mdp.d_qname;
        spoofed.d_type=dfepol.d_custom->getType();
@@ -821,7 +822,7 @@ void startDoResolve(void *p)
 
       if(ret.size()) {
         orderAndShuffle(ret);
-       if(auto sl = g_luaconfs.getCopy().sortlist.getOrderCmp(dc->d_remote)) {
+       if(auto sl = luaconfsLocal->sortlist.getOrderCmp(dc->d_remote)) {
          sort(ret.begin(), ret.end(), *sl);
          variableAnswer=true;
        }
@@ -2164,6 +2165,8 @@ int serviceMain(int argc, char*argv[])
   seedRandom(::arg()["entropy-source"]);
   g_disthashseed=dns_random(0xffffffff);
 
+  loadRecursorLuaConfig(::arg()["lua-config-file"]);
+
   parseACLs();
   sortPublicSuffixList();
 
@@ -2275,8 +2278,6 @@ int serviceMain(int argc, char*argv[])
   if(!s_pidfname.empty())
     unlink(s_pidfname.c_str()); // remove possible old pid file
 
-  loadRPZFiles();
-
   if(::arg().mustDo("daemon")) {
     L<<Logger::Warning<<"Calling daemonize, going to background"<<endl;
     L.toConsole(Logger::Critical);
@@ -2559,8 +2560,6 @@ int main(int argc, char **argv)
     ::arg().set("spoof-nearmiss-max", "If non-zero, assume spoofing after this many near misses")="20";
     ::arg().set("single-socket", "If set, only use a single socket for outgoing queries")="off";
     ::arg().set("auth-zones", "Zones for which we have authoritative data, comma separated domain=file pairs ")="";
-    ::arg().set("rpz-files", "RPZ files to load in order, domain or domain=policy pairs separated by commas")="";
-    ::arg().set("rpz-masters", "RPZ master servers, address:name pairs separated by commas")="";
     ::arg().set("lua-config-file", "More powerful configuration options")="";
 
     ::arg().set("forward-zones", "Zones for which we forward queries, comma separated domain=ip pairs")="";
@@ -2611,8 +2610,6 @@ int main(int argc, char **argv)
 
     ::arg().parse(argc,argv);
 
-    loadRecursorLuaConfig(::arg()["lua-config-file"]);
-
     ::arg().set("delegation-only")=toLower(::arg()["delegation-only"]);
 
     if(::arg().asNum("threads")==1)
index af2d90c1123e92fce3f53accddbcd50766e0acba..55c05f6372e860a457725da00b8801570b70e2e2 100644 (file)
@@ -4,10 +4,14 @@
 #endif
 
 #include <fstream>
+#include <thread>
 #include "namespaces.hh"
 #include "logger.hh"
 #include "rec-lua-conf.hh"
 #include "sortlist.hh"
+#include "filterpo.hh"
+#include "syncres.hh"
+#include "rpzloader.hh"
 
 GlobalStateHolder<LuaConfigItems> g_luaconfs;
 
@@ -28,6 +32,17 @@ LuaConfigItems::LuaConfigItems()
 {
 }
 
+/* DID YOU READ THE STORY ABOVE? */
+
+template <typename C>
+typename C::value_type::second_type constGet(const C& c, const std::string& name)
+{
+  auto iter = c.find(name);
+  if(iter == c.end())
+    return 0;
+  return iter->second;
+}
+
 #ifndef HAVE_LUA
 void loadRecursorLuaConfig(const std::string& fname)
 {
@@ -56,6 +71,81 @@ void loadRecursorLuaConfig(const std::string& fname)
                 {"1.2.3.4", {"4.5.6.7", "8.9.10.11"}}
   */
 
+  map<string,DNSFilterEngine::PolicyKind> pmap{
+    {"NoAction", DNSFilterEngine::PolicyKind::NoAction}, 
+    {"Drop", DNSFilterEngine::PolicyKind::Drop},
+    {"NXDOMAIN", DNSFilterEngine::PolicyKind::NXDOMAIN},
+    {"NODATA", DNSFilterEngine::PolicyKind::NODATA},
+    {"Truncate", DNSFilterEngine::PolicyKind::Truncate},
+    {"Custom", DNSFilterEngine::PolicyKind::Custom}
+  };
+  Lua.writeVariable("Policy", pmap);
+
+  Lua.writeFunction("rpzFile", [&lci](const string& fname, const boost::optional<std::unordered_map<string,boost::variant<int, string>>>& options) {
+      try {
+       boost::optional<DNSFilterEngine::Policy> defpol;
+       if(options) {
+         auto& have = *options;
+         if(have.count("defpol")) {
+           cout<<"Set a default policy"<<endl;
+           defpol=DNSFilterEngine::Policy();
+           defpol->d_kind = (DNSFilterEngine::PolicyKind)boost::get<int>(constGet(have, "defpol"));
+           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"))
+                                                                         )
+                                            );
+           }
+         }
+           
+       }
+       loadRPZFromFile(fname, lci.dfe, defpol, 0);
+      }
+      catch(std::exception& e) {
+       theL()<<Logger::Error<<"Unable to load RPZ zone from '"<<fname<<"': "<<e.what()<<endl;
+      }
+    });
+
+
+  Lua.writeFunction("rpzMaster", [&lci](const string& master_, const string& zone_, const boost::optional<std::unordered_map<string,boost::variant<int, string>>>& options) {
+      try {
+       boost::optional<DNSFilterEngine::Policy> defpol;
+       if(options) {
+         auto& have = *options;
+         if(have.count("defpol")) {
+           //      cout<<"Set a default policy"<<endl;
+           defpol=DNSFilterEngine::Policy();
+           defpol->d_kind = (DNSFilterEngine::PolicyKind)boost::get<int>(constGet(have, "defpol"));
+           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"))
+                                                                         )
+                                            );
+           }
+         }
+           
+       }
+       ComboAddress master(master_, 53);
+       DNSName zone(zone_);
+       auto sr=loadRPZFromServer(master,zone, lci.dfe, defpol, 0);
+       std::thread t(RPZIXFRTracker, master, zone, sr);
+       t.detach();
+      }
+      catch(std::exception& e) {
+       theL()<<Logger::Error<<"Unable to load RPZ zone '"<<zone_<<"' from '"<<master_<<"': "<<e.what()<<endl;
+      }
+      catch(PDNSException& e) {
+       theL()<<Logger::Error<<"Unable to load RPZ zone '"<<zone_<<"' from '"<<master_<<"': "<<e.reason<<endl;
+      }
+
+    });
+
   typedef vector<pair<int,boost::variant<string, vector<pair<int, string> > > > > argvec_t;
   Lua.writeFunction("addSortList", 
                    [&lci](const std::string& formask_, 
@@ -87,8 +177,14 @@ void loadRecursorLuaConfig(const std::string& fname)
                        theL()<<Logger::Error<<"Error in addSortList: "<<e.what()<<endl;
                      }
                    });
-  Lua.executeCode(ifs);
-  g_luaconfs.setState(lci);
+  try {
+    Lua.executeCode(ifs);
+    g_luaconfs.setState(lci);
+  }
+  catch(std::exception& err) {
+    theL()<<Logger::Error<<"Unable to load Lua script from '"+fname+"': "<<err.what()<<endl;
+  }
+
 }
 
 #endif
index 88663c29d48822b6e19a9986bc8f732297cfdd76..226f16c0aa72da81d33422406769387d7d3fe925 100644 (file)
@@ -1,11 +1,14 @@
 #pragma once
 #include "sholder.hh"
 #include "sortlist.hh"
+#include "filterpo.hh"
+
 class LuaConfigItems 
 {
 public:
   LuaConfigItems();
   SortList sortlist;
+  DNSFilterEngine dfe;
 };
 
 extern GlobalStateHolder<LuaConfigItems> g_luaconfs;
index 5c364c542e65619ab53c30962a7fe86a73255089..abcd9349853739fabba5985fc2d6bc914479fa36 100644 (file)
@@ -28,7 +28,7 @@
 #include "zoneparser-tng.hh"
 #include "logger.hh"
 #include "dnsrecords.hh"
-
+#include "rec-lua-conf.hh"
 #include <thread>
 #include "ixfr.hh"
 #include "rpzloader.hh"
@@ -316,7 +316,8 @@ string reloadAuthAndForwards()
   return "reloading failed, see log\n";
 }
 
-void ixfrTracker(const ComboAddress& master, const DNSName& zone, shared_ptr<SOARecordContent> oursr) 
+
+void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, shared_ptr<SOARecordContent> oursr) 
 {
   for(;;) {
     DNSRecord dr;
@@ -324,14 +325,14 @@ void ixfrTracker(const ComboAddress& master, const DNSName& zone, shared_ptr<SOA
 
     sleep(oursr->d_st.refresh);
     
-
     L<<Logger::Info<<"Getting IXFR deltas for "<<zone<<" from "<<master.toStringWithPort()<<", our serial: "<<std::dynamic_pointer_cast<SOARecordContent>(dr.d_content)->d_st.serial<<endl;
 
     auto deltas = getIXFRDeltas(master, zone, dr);
     if(deltas.empty())
       continue;
-    L<<Logger::Info<<"Processing "<<deltas.size()<<" deltas for RPZ "<<zone<<endl;
+    L<<Logger::Info<<"Processing "<<deltas.size()<<" delta"<<addS(deltas)<<" for RPZ "<<zone<<endl;
 
+    auto luaconfsCopy = g_luaconfs.getCopy();
     int totremove=0, totadd=0;
     for(const auto& delta : deltas) {
       const auto& remove = delta.first;
@@ -345,11 +346,11 @@ void ixfrTracker(const ComboAddress& master, const DNSName& zone, shared_ptr<SOA
            //      cout<<"Got good removal of SOA serial "<<oldsr->d_st.serial<<endl;
          }
          else
-           cerr<<"GOT WRONG SOA SERIAL REMOVAL, SHOULD TRIGGER WHOLE RELOAD"<<endl;
+           L<<Logger::Error<<"GOT WRONG SOA SERIAL REMOVAL, SHOULD TRIGGER WHOLE RELOAD"<<endl;
        }
        else {
          L<<Logger::Info<<"Had removal of "<<rr.d_name<<endl;
-         RPZRecordToPolicy(rr, g_dfe, false, 0);
+         RPZRecordToPolicy(rr, luaconfsCopy.dfe, false, boost::optional<DNSFilterEngine::Policy>(), 0);
        }
       }
 
@@ -362,36 +363,13 @@ void ixfrTracker(const ComboAddress& master, const DNSName& zone, shared_ptr<SOA
        }
        else {
          L<<Logger::Info<<"Had addition of "<<rr.d_name<<endl;
-         RPZRecordToPolicy(rr, g_dfe, true, 0);
+         RPZRecordToPolicy(rr, luaconfsCopy.dfe, true, boost::optional<DNSFilterEngine::Policy>(), 0);
        }
       }
     }
-    L<<Logger::Info<<"Had "<<totremove<<" RPZ removals, "<<totadd<<" additions for "<<zone<<" New serial: "<<oursr->d_st.serial<<endl;
-  }
-}
-
-
-void loadRPZFiles()
-{
-  vector<string> fnames;
-  stringtok(fnames, ::arg()["rpz-files"]," ,");
-  int count=0;
-  for(const auto& f : fnames) {
-    loadRPZFromFile(f, g_dfe, count++);
-  }
-
-  fnames.clear();
-  stringtok(fnames, ::arg()["rpz-masters"]," ,");
-
-  for(const auto& f : fnames) {
-    auto s = splitField(f, ':');
-    ComboAddress master(s.first, 53);
-    DNSName zone(s.second);
-    auto sr=loadRPZFromServer(master,zone, g_dfe, count++);
-    std::thread t(ixfrTracker, master, zone, sr);
-    t.detach();
+    L<<Logger::Info<<"Had "<<totremove<<" RPZ removal"<<addS(totremove)<<", "<<totadd<<" addition"<<addS(totadd)<<" for "<<zone<<" New serial: "<<oursr->d_st.serial<<endl;
+    g_luaconfs.setState(luaconfsCopy);
   }
-
 }
 
 SyncRes::domainmap_t* parseAuthAndForwards()
index 8f7c36366968690ae5cc7247207d62efe282a5b3..bfdfd13aea2b9346c9d5eac2a8a4ab251f48af02 100644 (file)
@@ -5,6 +5,7 @@
 #include "syncres.hh"
 #include "resolver.hh"
 #include "logger.hh"
+#include "rec-lua-conf.hh"
 
 static Netmask makeNetmaskFromRPZ(const DNSName& name)
 {
@@ -14,7 +15,7 @@ static Netmask makeNetmaskFromRPZ(const DNSName& name)
   return Netmask(parts[4]+"."+parts[3]+"."+parts[2]+"."+parts[1]+"/"+parts[0]);
 }
 
-void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, bool addOrRemove, int place)
+void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, bool addOrRemove, boost::optional<DNSFilterEngine::Policy> defpol, int place)
 {
   static const DNSName drop("rpz-drop."), truncate("rpz-tcp-only."), noaction("rpz-passthru.");
   static const DNSName rpzClientIP("rpz-client-ip"), rpzIP("rpz-ip"),
@@ -24,7 +25,10 @@ void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, bool addOrR
 
   if(dr.d_type == QType::CNAME) {
     auto target=std::dynamic_pointer_cast<CNAMERecordContent>(dr.d_content)->getTarget();
-    if(target.isRoot()) {
+    if(defpol) {
+      pol=*defpol;
+    }
+    else if(target.isRoot()) {
       // cerr<<"Wants NXDOMAIN for "<<dr.d_name<<": ";
       pol.d_kind = DNSFilterEngine::PolicyKind::NXDOMAIN;
     } else if(target==DNSName("*")) {
@@ -60,37 +64,37 @@ void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, bool addOrR
   if(dr.d_name.isPartOf(rpzNSDname)) {
     DNSName filt=dr.d_name.makeRelative(rpzNSDname);
     if(addOrRemove)
-      g_dfe.addNSTrigger(filt, pol);
+      target.addNSTrigger(filt, pol);
     else
-      g_dfe.rmNSTrigger(filt, pol);
+      target.rmNSTrigger(filt, pol);
   } else       if(dr.d_name.isPartOf(rpzClientIP)) {
 
     auto nm=makeNetmaskFromRPZ(dr.d_name);
 
     if(addOrRemove)
-      g_dfe.addClientTrigger(nm, pol);
+      target.addClientTrigger(nm, pol);
     else
-      g_dfe.rmClientTrigger(nm, pol);
+      target.rmClientTrigger(nm, pol);
     
   } else       if(dr.d_name.isPartOf(rpzIP)) {
     // cerr<<"Should apply answer content IP policy: "<<dr.d_name<<endl;
     auto nm=makeNetmaskFromRPZ(dr.d_name);
     if(addOrRemove)
-      g_dfe.addResponseTrigger(nm, pol);
+      target.addResponseTrigger(nm, pol);
     else
-      g_dfe.rmResponseTrigger(nm, pol);
+      target.rmResponseTrigger(nm, pol);
   } else if(dr.d_name.isPartOf(rpzNSIP)) {
     cerr<<"Should apply to nameserver IP address policy HAVE NOTHING HERE"<<endl;
 
   } else {
     if(addOrRemove)
-      g_dfe.addQNameTrigger(dr.d_name, pol);
+      target.addQNameTrigger(dr.d_name, pol);
     else
-      g_dfe.rmQNameTrigger(dr.d_name, pol);
+      target.rmQNameTrigger(dr.d_name, pol);
   }
 }
 
-shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const DNSName& zone, DNSFilterEngine& target, int place)
+shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const DNSName& zone, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, int place)
 {
   L<<Logger::Warning<<"Loading RPZ zone '"<<zone<<"' from "<<master.toStringWithPort()<<endl;
   ComboAddress local("0.0.0.0");
@@ -111,7 +115,7 @@ shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const
        continue;
       }
 
-      RPZRecordToPolicy(dr, target, true, place);
+      RPZRecordToPolicy(dr, target, true, defpol, place);
       nrecords++;
     } 
     if(last != time(0)) {
@@ -123,7 +127,7 @@ shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const
   return sr;
 }
 
-int loadRPZFromFile(const std::string& fname, DNSFilterEngine& target, int place)
+int loadRPZFromFile(const std::string& fname, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, int place)
 {
   ZoneParserTNG zpt(fname);
   DNSResourceRecord drr;
@@ -142,7 +146,7 @@ int loadRPZFromFile(const std::string& fname, DNSFilterEngine& target, int place
       }
       else {
        dr.d_name=dr.d_name.makeRelative(domain);
-       RPZRecordToPolicy(dr, target, true, place);
+       RPZRecordToPolicy(dr, target, true, defpol, place);
       }
     }
     catch(PDNSException& pe) {
index 57d7ce07c546406b816334c95272003a4e33e8f1..42b8fba11e803620253260284b59e8b476f5a453 100644 (file)
@@ -3,6 +3,7 @@
 #include <string>
 #include "dnsrecords.hh"
 
-int loadRPZFromFile(const std::string& fname, DNSFilterEngine& target, int place);
-std::shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const DNSName& zone, DNSFilterEngine& target, int place);
-void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, bool addOrRemove, int place);
+int loadRPZFromFile(const std::string& fname, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, int place);
+std::shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const DNSName& zone, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, int place);
+void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, bool addOrRemove, boost::optional<DNSFilterEngine::Policy> defpol, int place);
+void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, shared_ptr<SOARecordContent> oursr);
index 7684066060edc2b1ca74b6d2a1139719a3667cd4..e0e39ca411d32df3886c9980642995716b2f1f7d 100644 (file)
@@ -49,7 +49,7 @@
 #include "lock.hh"
 #include "ednssubnet.hh"
 #include "cachecleaner.hh"
-
+#include "rec-lua-conf.hh"
 __thread SyncRes::StaticStorage* t_sstorage;
 
 unsigned int SyncRes::s_maxnegttl;
@@ -956,7 +956,7 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
        ;
 
        // XXX NEED TO HANDLE OTHER POLICY KINDS HERE!
-       if(g_dfe.getProcessingPolicy(*tns).d_kind != DNSFilterEngine::PolicyKind::NoAction)
+       if(g_luaconfs.getLocal()->dfe.getProcessingPolicy(*tns).d_kind != DNSFilterEngine::PolicyKind::NoAction)
          throw ImmediateServFailException("Dropped because of policy");
 
         if(!isCanonical(*tns)) {
index 3988c082f1670da5099fa3153b5bdc51e5951585..148b6d86e7959407e7e8ae3978a843691ca828dc 100644 (file)
@@ -24,8 +24,6 @@
 #include "iputils.hh"
 #include "filterpo.hh"
 
-extern DNSFilterEngine g_dfe;
-
 void primeHints(void);
 class RecursorLua;
 
@@ -658,8 +656,6 @@ int directResolve(const DNSName& qname, const QType& qtype, int qclass, vector<D
 template<class T> T broadcastAccFunction(const boost::function<T*()>& func, bool skipSelf=false);
 
 SyncRes::domainmap_t* parseAuthAndForwards();
-void loadRPZFiles();
-
 uint64_t* pleaseGetNsSpeedsSize();
 uint64_t* pleaseGetCacheSize();
 uint64_t* pleaseGetNegCacheSize();