NetmaskGroup g_ednssubnets;
SuffixMatchNode g_ednsdomains;
-DNSFilterEngine g_dfe;
-
RecursorControlChannel s_rcc; // only active in thread 0
// for communicating with our threads
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;
// 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:
res = RCode::ServFail;
}
- dfepol = g_dfe.getPostPolicy(ret);
+ dfepol = luaconfsLocal->dfe.getPostPolicy(ret);
switch(dfepol.d_kind) {
case DNSFilterEngine::PolicyKind::NoAction:
break;
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();
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;
}
seedRandom(::arg()["entropy-source"]);
g_disthashseed=dns_random(0xffffffff);
+ loadRecursorLuaConfig(::arg()["lua-config-file"]);
+
parseACLs();
sortPublicSuffixList();
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);
::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")="";
::arg().parse(argc,argv);
- loadRecursorLuaConfig(::arg()["lua-config-file"]);
-
::arg().set("delegation-only")=toLower(::arg()["delegation-only"]);
if(::arg().asNum("threads")==1)
#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;
{
}
+/* 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)
{
{"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_,
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
#pragma once
#include "sholder.hh"
#include "sortlist.hh"
+#include "filterpo.hh"
+
class LuaConfigItems
{
public:
LuaConfigItems();
SortList sortlist;
+ DNSFilterEngine dfe;
};
extern GlobalStateHolder<LuaConfigItems> g_luaconfs;
#include "zoneparser-tng.hh"
#include "logger.hh"
#include "dnsrecords.hh"
-
+#include "rec-lua-conf.hh"
#include <thread>
#include "ixfr.hh"
#include "rpzloader.hh"
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;
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;
// 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);
}
}
}
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()
#include "syncres.hh"
#include "resolver.hh"
#include "logger.hh"
+#include "rec-lua-conf.hh"
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"),
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("*")) {
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");
continue;
}
- RPZRecordToPolicy(dr, target, true, place);
+ RPZRecordToPolicy(dr, target, true, defpol, place);
nrecords++;
}
if(last != time(0)) {
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;
}
else {
dr.d_name=dr.d_name.makeRelative(domain);
- RPZRecordToPolicy(dr, target, true, place);
+ RPZRecordToPolicy(dr, target, true, defpol, place);
}
}
catch(PDNSException& pe) {
#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);
#include "lock.hh"
#include "ednssubnet.hh"
#include "cachecleaner.hh"
-
+#include "rec-lua-conf.hh"
__thread SyncRes::StaticStorage* t_sstorage;
unsigned int SyncRes::s_maxnegttl;
;
// 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)) {
#include "iputils.hh"
#include "filterpo.hh"
-extern DNSFilterEngine g_dfe;
-
void primeHints(void);
class RecursorLua;
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();