});
+ g_lua.writeFunction("setDNSSECPool", [](const std::string& pool) {
+ g_rulactions.modify([pool](decltype(g_rulactions)::value_type& rulactions) {
+ rulactions.push_back({std::make_shared<DNSSECRule>(),
+ std::make_shared<PoolAction>(pool)});
+ });
+ });
g_lua.writeFunction("addQPSLimit", [](boost::variant<string,vector<pair<int, string>> > var, int lim) {
SuffixMatchNode smn;
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<std::mutex> lock(g_rings.respMutex);
+ ring = g_rings.respRing;
+ }
+ vector<std::unordered_map<string, boost::variant<string, unsigned int> > > 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<int> labels) {
map<DNSName, int> counts;
unsigned int total=0;
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
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;
}
}
}
+
+
int main(int argc, char** argv)
try
{
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<uint64_t> d_matches{0};
};
{
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;
};
std::shared_ptr<DownstreamState> leastOutstanding(const NumberedServerVector& servers, const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh);
std::shared_ptr<DownstreamState> wrandom(const NumberedServerVector& servers, const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh);
std::shared_ptr<DownstreamState> roundrobin(const NumberedServerVector& servers, const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh);
-
+int getEDNSZ(const char* packet, unsigned int len);
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
-- 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
}
// 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;
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);
}
return ret;
}
+
+
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)
// 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);
};
{
}
- 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);
}
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);
}
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;
}
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;
}
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;
{
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;
{
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
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