From: bert hubert Date: Wed, 18 Mar 2015 07:10:33 +0000 (+0100) Subject: add DNSSEC selection rule, plus setDNSSECPool() command X-Git-Tag: dnsdist-1.0.0-alpha1~248^2~88^2~40 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=520eb5a01fceaee87171a9dd1dbeb6a32c0b4a9f;p=thirdparty%2Fpdns.git add DNSSEC selection rule, plus setDNSSECPool() command --- diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index df473acd87..74a5ab6dec 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -268,6 +268,12 @@ vector> setupLua(bool client) }); + g_lua.writeFunction("setDNSSECPool", [](const std::string& pool) { + g_rulactions.modify([pool](decltype(g_rulactions)::value_type& rulactions) { + rulactions.push_back({std::make_shared(), + std::make_shared(pool)}); + }); + }); g_lua.writeFunction("addQPSLimit", [](boost::variant> > var, int lim) { SuffixMatchNode smn; @@ -485,6 +491,26 @@ vector> setupLua(bool client) g_lua.executeCode(R"(function topQueries(top, labels) for k,v in ipairs(getTopQueries(top,labels)) do show(string.format("%4d %-40s %4d %4.1f%%",k,v[1],v[2], v[3])) end end)"); + + g_lua.writeFunction("getResponseRing", []() { + decltype(g_rings.respRing) ring; + { + std::lock_guard lock(g_rings.respMutex); + ring = g_rings.respRing; + } + vector > > ret; + ret.reserve(ring.size()); + decltype(ret)::value_type item; + for(const auto& r : ring) { + item["name"]=r.name.toString(); + item["qtype"]=r.qtype; + item["rcode"]=r.rcode; + item["usec"]=r.usec; + ret.push_back(item); + } + return ret; + }); + g_lua.writeFunction("getTopResponses", [](unsigned int top, unsigned int kind, boost::optional labels) { map counts; unsigned int total=0; diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index 4888bd0a8e..8de15d2465 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -263,6 +263,27 @@ NumberedServerVector getDownstreamCandidates(const servers_t& servers, const std return ret; } +// goal in life - if you send us a reasonably normal packet, we'll get Z for you, otherwise 0 +int getEDNSZ(const char* packet, unsigned int len) +{ + struct dnsheader* dh =(struct dnsheader*)packet; + + if(dh->ancount!=0 && ntohs(dh->arcount)!=1 && dh->nscount!=0) + return 0; + + unsigned int consumed; + DNSName qname(packet, len, 12, false, 0, 0, &consumed); + int pos = consumed + 4; + uint16_t qtype, qclass; + + DNSName aname(packet, len, 12+pos, false, &qtype, &qclass, &consumed); + + if(qtype!=QType::OPT || 12+pos+consumed+7 >= len) + return 0; + + uint8_t* z = (uint8_t*)packet+12+pos+consumed+6; + return 0x100 * (*z) + *(z+1); +} // listens to incoming queries, sends out to downstream servers, noting the intended return path @@ -329,10 +350,11 @@ try DNSAction::Action action=DNSAction::Action::None; string ruleresult; string pool; + for(const auto& lr : *localRulactions) { - if(lr.first->matches(remote, qname, qtype, dh)) { + if(lr.first->matches(remote, qname, qtype, dh, len)) { lr.first->d_matches++; - action=(*lr.second)(remote, qname, qtype, dh, &ruleresult); + action=(*lr.second)(remote, qname, qtype, dh, len, &ruleresult); if(action != DNSAction::Action::None) break; } @@ -987,6 +1009,8 @@ static char** my_completion( const char * text , int start, int end) } } + + int main(int argc, char** argv) try { diff --git a/pdns/dnsdist.hh b/pdns/dnsdist.hh index cdaacd8145..b042558e27 100644 --- a/pdns/dnsdist.hh +++ b/pdns/dnsdist.hh @@ -201,7 +201,7 @@ extern std::string g_outputBuffer; // locking for this is ok, as locked by g_lua class DNSRule { public: - virtual bool matches(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh) const =0; + virtual bool matches(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, int len) const =0; virtual string toString() const = 0; mutable std::atomic d_matches{0}; }; @@ -219,7 +219,7 @@ class DNSAction { public: enum class Action { Drop, Nxdomain, Spoof, Allow, HeaderModify, Pool, None}; - virtual Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, string* ruleresult) const =0; + virtual Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, int len, string* ruleresult) const =0; virtual string toString() const = 0; }; @@ -257,7 +257,7 @@ std::shared_ptr firstAvailable(const NumberedServerVector& serv std::shared_ptr leastOutstanding(const NumberedServerVector& servers, const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh); std::shared_ptr wrandom(const NumberedServerVector& servers, const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh); std::shared_ptr roundrobin(const NumberedServerVector& servers, const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh); - +int getEDNSZ(const char* packet, unsigned int len); template std::unique_ptr make_unique(Args&&... args) { diff --git a/pdns/dnsdistconf.lua b/pdns/dnsdistconf.lua index 6cbc8ea4c0..e844e6ee78 100644 --- a/pdns/dnsdistconf.lua +++ b/pdns/dnsdistconf.lua @@ -55,9 +55,12 @@ end -- setServerPolicyLua("luaroundrobin", luaroundrobin) -newServer{address="2001:888:2000:1d::2", pool="auth"} +xs=newServer{address="2001:888:2000:1d::2", pool="auth"} newServer{address="2a01:4f8:110:4389::2", pool="auth"} +xs:addPool("dnssec") +setDNSSECPool("dnssec") + function splitSetup(servers, remote, qname, qtype, dh) if(dh:getRD() == false) then diff --git a/pdns/dnsname.cc b/pdns/dnsname.cc index 8616c7c3a1..7dc051e0ca 100644 --- a/pdns/dnsname.cc +++ b/pdns/dnsname.cc @@ -24,7 +24,7 @@ DNSName::DNSName(const char* p) } // this should be the __only__ dns name parser in PowerDNS. -DNSName::DNSName(const char* pos, int len, int offset, bool uncompress, uint16_t* qtype, uint16_t* qclass) +DNSName::DNSName(const char* pos, int len, int offset, bool uncompress, uint16_t* qtype, uint16_t* qclass, unsigned int* consumed) { unsigned char labellen; const char *opos = pos; @@ -45,6 +45,8 @@ DNSName::DNSName(const char* pos, int len, int offset, bool uncompress, uint16_t appendRawLabel(string(pos, labellen)); pos+=labellen; } + if(consumed) + *consumed = pos - opos - offset; if(qtype && pos + labellen + 2 <= end) *qtype=(*(const unsigned char*)pos)*256 + *((const unsigned char*)pos+1); @@ -180,3 +182,5 @@ string DNSName::escapeLabel(const std::string& label) } return ret; } + + diff --git a/pdns/dnsname.hh b/pdns/dnsname.hh index b83a183f0e..ea99a6389d 100644 --- a/pdns/dnsname.hh +++ b/pdns/dnsname.hh @@ -25,7 +25,7 @@ public: DNSName() {} //!< Constructs the root name DNSName(const char* p); //!< Constructs from a human formatted, escaped presentation DNSName(const std::string& str) : DNSName(str.c_str()) {} //!< Constructs from a human formatted, escaped presentation - DNSName(const char* p, int len, int offset, bool uncompress, uint16_t* qtype=0, uint16_t* qclass=0); //!< Construct from a DNS Packet, taking the first question + DNSName(const char* p, int len, int offset, bool uncompress, uint16_t* qtype=0, uint16_t* qclass=0, unsigned int* consumed=0); //!< Construct from a DNS Packet, taking the first question bool isPartOf(const DNSName& rhs) const; //!< Are we part of the rhs name? bool operator==(const DNSName& rhs) const; //!< DNS-native comparison (case insensitive) @@ -56,6 +56,7 @@ private: // typedef __gnu_cxx::__sso_string string_t; typedef std::string string_t; string_t d_storage; + static std::string escapeLabel(const std::string& orig); static std::string unescapeLabel(const std::string& orig); }; diff --git a/pdns/dnsrulactions.hh b/pdns/dnsrulactions.hh index dd8a76e65b..623f345f6d 100644 --- a/pdns/dnsrulactions.hh +++ b/pdns/dnsrulactions.hh @@ -8,7 +8,7 @@ public: { } - bool matches(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh) const override + bool matches(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, int len) const override { return d_nmg.match(remote); } @@ -21,13 +21,32 @@ private: NetmaskGroup d_nmg; }; +class DNSSECRule : public DNSRule +{ +public: + DNSSECRule() + { + + } + bool matches(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, int len) const override + { + return dh->cd || (getEDNSZ((const char*)dh, len) & 32768); // turns out dig sets ad by default.. + } + + string toString() const override + { + return "DNSSEC"; + } +}; + + class SuffixMatchNodeRule : public DNSRule { public: SuffixMatchNodeRule(const SuffixMatchNode& smn) : d_smn(smn) { } - bool matches(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh) const override + bool matches(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, int len) const override { return d_smn.check(qname); } @@ -45,7 +64,7 @@ public: QTypeRule(uint16_t qtype) : d_qtype(qtype) { } - bool matches(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh) const override + bool matches(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, int len) const override { return d_qtype == qtype; } @@ -61,7 +80,7 @@ private: class DropAction : public DNSAction { public: - DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, string* ruleresult) const override + DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, int len, string* ruleresult) const override { return Action::Drop; } @@ -76,7 +95,7 @@ class QPSAction : public DNSAction public: QPSAction(int limit) : d_qps(limit, limit) {} - DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, string* ruleresult) const override + DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, int len, string* ruleresult) const override { if(d_qps.check()) return Action::Allow; @@ -95,7 +114,7 @@ class PoolAction : public DNSAction { public: PoolAction(const std::string& pool) : d_pool(pool) {} - DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, string* ruleresult) const override + DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, int len, string* ruleresult) const override { *ruleresult=d_pool; return Action::Pool; @@ -113,7 +132,7 @@ class RCodeAction : public DNSAction { public: RCodeAction(int rcode) : d_rcode(rcode) {} - DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, string* ruleresult) const override + DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, int len, string* ruleresult) const override { dh->rcode = d_rcode; dh->qr = true; // for good measure @@ -131,7 +150,7 @@ private: class TCAction : public DNSAction { public: - DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, string* ruleresult) const override + DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, int len, string* ruleresult) const override { dh->tc = true; dh->qr = true; // for good measure