From 731774a8c4e520a5ffee0ed293ff831a8fa6e728 Mon Sep 17 00:00:00 2001 From: bert hubert Date: Thu, 10 Dec 2015 12:55:09 +0100 Subject: [PATCH] new function: addDomainSpoof("domain", "ipv4", "ipv6"). Also, DNSActions can now modify packet length. --- pdns/dnsdist-ecs.cc | 4 +-- pdns/dnsdist-ecs.hh | 2 +- pdns/dnsdist-lua.cc | 34 +++++++++++++++++++-- pdns/dnsdist-tcp.cc | 4 +-- pdns/dnsdist.cc | 9 +++--- pdns/dnsdist.hh | 2 +- pdns/dnsrulactions.hh | 71 +++++++++++++++++++++++++++++++++++++------ 7 files changed, 104 insertions(+), 22 deletions(-) diff --git a/pdns/dnsdist-ecs.cc b/pdns/dnsdist-ecs.cc index b0d5e2e6a..91ac2a992 100644 --- a/pdns/dnsdist-ecs.cc +++ b/pdns/dnsdist-ecs.cc @@ -284,7 +284,7 @@ static void generateECSOptRR(const ComboAddress& source, string & res) res.append(optRData.c_str(), optRData.length()); } -static void replaceEDNSClientSubnetOption(char * const packet, const size_t packetSize, int * const len, string& largerPacket, const ComboAddress& remote, char * const oldEcsOptionStart, size_t const oldEcsOptionSize, uint16_t * const optRDLen) +static void replaceEDNSClientSubnetOption(char * const packet, const size_t packetSize, uint16_t * const len, string& largerPacket, const ComboAddress& remote, char * const oldEcsOptionStart, size_t const oldEcsOptionSize, uint16_t * const optRDLen) { assert(packet != NULL); assert(len != NULL); @@ -333,7 +333,7 @@ static void replaceEDNSClientSubnetOption(char * const packet, const size_t pack } } -void handleEDNSClientSubnet(char * const packet, const size_t packetSize, const unsigned int consumed, int * const len, string& largerPacket, bool * const ednsAdded, const ComboAddress& remote) +void handleEDNSClientSubnet(char * const packet, const size_t packetSize, const unsigned int consumed, uint16_t * const len, string& largerPacket, bool * const ednsAdded, const ComboAddress& remote) { assert(packet != NULL); assert(len != NULL); diff --git a/pdns/dnsdist-ecs.hh b/pdns/dnsdist-ecs.hh index 4edbac7f0..74138fdda 100644 --- a/pdns/dnsdist-ecs.hh +++ b/pdns/dnsdist-ecs.hh @@ -2,7 +2,7 @@ int rewriteResponseWithoutEDNS(const char * packet, size_t len, vector& newContent); int locateEDNSOptRR(const char * packet, size_t len, const char ** optStart, size_t * optLen, bool * last); -void handleEDNSClientSubnet(char * packet, size_t packetSize, unsigned int consumed, int * len, string& largerPacket, bool * ednsAdded, const ComboAddress& remote); +void handleEDNSClientSubnet(char * packet, size_t packetSize, unsigned int consumed, uint16_t * len, string& largerPacket, bool * ednsAdded, const ComboAddress& remote); diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index 772e10719..45a8d0c70 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -18,7 +18,7 @@ public: LuaAction(LuaAction::func_t func) : d_func(func) {} - Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, int len, string* ruleresult) const + Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, uint16_t& len, string* ruleresult) const override { auto ret = d_func(remote, qname, qtype, dh, len); if(ruleresult) @@ -78,7 +78,6 @@ vector> setupLua(bool client, const std::string& confi {"Pool", (int)DNSAction::Action::Pool}, {"None",(int)DNSAction::Action::Pool}} ); - g_lua.writeFunction("newServer", [client](boost::variant pvars, boost::optional qps) @@ -400,6 +399,37 @@ vector> setupLua(bool client, const std::string& confi return std::shared_ptr(new NoRecurseAction); }); + g_lua.writeFunction("SpoofAction", [](const string& a, boost::optional b) { + if(b) + return std::shared_ptr(new SpoofAction(ComboAddress(a), ComboAddress(*b))); + else + return std::shared_ptr(new SpoofAction(ComboAddress(a))); + }); + + g_lua.writeFunction("addDomainSpoof", [](const std::string& domain, const std::string& ip, boost::optional ip6) { + SuffixMatchNode smn; + ComboAddress a, b; + b.sin6.sin6_family=0; + try + { + smn.add(DNSName(domain)); + a=ComboAddress(ip); + if(ip6) + b=ComboAddress(*ip6); + } + catch(std::exception& e) { + g_outputBuffer="Error parsing parameters: "+string(e.what()); + return; + } + g_rulactions.modify([&smn,&a,&b](decltype(g_rulactions)::value_type& rulactions) { + rulactions.push_back({ + std::make_shared(smn), + std::make_shared(a, b) }); + }); + + }); + + g_lua.writeFunction("DropAction", []() { return std::shared_ptr(new DropAction); }); diff --git a/pdns/dnsdist-tcp.cc b/pdns/dnsdist-tcp.cc index 77e63045b..a92820c96 100644 --- a/pdns/dnsdist-tcp.cc +++ b/pdns/dnsdist-tcp.cc @@ -160,7 +160,7 @@ void* tcpClientThread(int pipefd) char queryBuffer[qlen]; const char * query = queryBuffer; - size_t queryLen = qlen; + uint16_t queryLen = qlen; readn2WithTimeout(ci.fd, queryBuffer, queryLen, g_tcpRecvTimeout); uint16_t qtype; unsigned int consumed = 0; @@ -262,7 +262,7 @@ void* tcpClientThread(int pipefd) } if (ds->useECS) { - int newLen = queryLen; + uint16_t newLen = queryLen; handleEDNSClientSubnet(queryBuffer, queryLen, consumed, &newLen, largerQuery, &ednsAdded, ci.remote); if (largerQuery.empty() == false) { query = largerQuery.c_str(); diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index d8080c237..69ef44e8a 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -452,7 +452,6 @@ try remote.sin4.sin_family = cs->local.sin4.sin_family; char packet[1500]; struct dnsheader* dh = (struct dnsheader*) packet; - int len; string largerQuery; uint16_t qtype; @@ -481,16 +480,16 @@ try for(;;) { try { - len = recvmsg(cs->udpFD, &msgh, 0); + int ret = recvmsg(cs->udpFD, &msgh, 0); cs->queries++; g_stats.queries++; - if(len < (int)sizeof(struct dnsheader)) { + if(ret < (int)sizeof(struct dnsheader)) { g_stats.nonCompliantQueries++; continue; } - + uint16_t len=ret; if (msgh.msg_flags & MSG_TRUNC) { /* message was too large for our buffer */ vinfolog("Dropping message too large for our buffer"); @@ -521,7 +520,7 @@ try clock_gettime(CLOCK_MONOTONIC, &now); { WriteLock wl(&g_rings.queryLock); - g_rings.queryRing.push_back({now,remote,qname,(uint16_t)len,qtype, *dh}); + g_rings.queryRing.push_back({now,remote,qname,len,qtype, *dh}); } if(auto got=localDynBlock->lookup(remote)) { diff --git a/pdns/dnsdist.hh b/pdns/dnsdist.hh index 115361f7c..597ce1a5e 100644 --- a/pdns/dnsdist.hh +++ b/pdns/dnsdist.hh @@ -356,7 +356,7 @@ class DNSAction { public: enum class Action { Drop, Nxdomain, Spoof, Allow, HeaderModify, Pool, Delay, None}; - virtual Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, int len, string* ruleresult) const =0; + virtual Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, uint16_t& len, string* ruleresult) const =0; virtual string toString() const = 0; }; diff --git a/pdns/dnsrulactions.hh b/pdns/dnsrulactions.hh index 5712b774b..81375622e 100644 --- a/pdns/dnsrulactions.hh +++ b/pdns/dnsrulactions.hh @@ -140,7 +140,7 @@ private: class DropAction : public DNSAction { public: - DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, int len, string* ruleresult) const override + DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, uint16_t& len, string* ruleresult) const override { return Action::Drop; } @@ -156,7 +156,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, int len, string* ruleresult) const override + DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, uint16_t& len, string* ruleresult) const override { if(d_qps.check()) return Action::Allow; @@ -176,7 +176,7 @@ class DelayAction : public DNSAction public: DelayAction(int msec) : d_msec(msec) {} - DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, int len, string* ruleresult) const override + DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, uint16_t& len, string* ruleresult) const override { *ruleresult=std::to_string(d_msec); return Action::Delay; @@ -194,7 +194,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, int len, string* ruleresult) const override + DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, uint16_t& len, string* ruleresult) const override { *ruleresult=d_pool; return Action::Pool; @@ -213,7 +213,7 @@ class QPSPoolAction : public DNSAction { public: QPSPoolAction(unsigned int limit, const std::string& pool) : d_qps(limit, limit), d_pool(pool) {} - DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, int len, string* ruleresult) const override + DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, uint16_t& len, string* ruleresult) const override { if(d_qps.check()) { *ruleresult=d_pool; @@ -236,7 +236,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, int len, string* ruleresult) const override + DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, uint16_t& len, string* ruleresult) const override { dh->rcode = d_rcode; dh->qr = true; // for good measure @@ -254,7 +254,7 @@ private: class TCAction : public DNSAction { public: - DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, int len, string* ruleresult) const override + DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, uint16_t& len, string* ruleresult) const override { dh->tc = true; dh->qr = true; // for good measure @@ -266,10 +266,63 @@ public: } }; +class SpoofAction : public DNSAction +{ +public: + SpoofAction(const ComboAddress& a) : d_a(a) { d_aaaa.sin4.sin_family = 0;} + SpoofAction(const ComboAddress& a, const ComboAddress& aaaa) : d_a(a), d_aaaa(aaaa) {} + DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, uint16_t& len, string* ruleresult) const override + { + if((qtype == QType::A && d_a.sin4.sin_family == 0) || + (qtype == QType::AAAA && d_aaaa.sin4.sin_family == 0) || (qtype != QType::A && qtype != QType::AAAA)) + return Action::None; + + dh->qr = true; // for good measure + dh->ra = dh->rd; // for good measure + dh->ad = false; + dh->ancount = htons(1); + dh->arcount = 0; // for now, forget about your EDNS, we're marching over it + unsigned int consumed=0; + + DNSName ignore((char*)dh, len, sizeof(dnsheader), false, 0, 0, &consumed); + + char* dest = ((char*)dh) +sizeof(dnsheader) + consumed + 4; + uint8_t addrlen = qtype == QType::A ? 4 : 16; + + const unsigned char recordstart[]={0xc0, 0x0c, // compressed name + 0, (unsigned char) qtype, + 0, 1, // IN + 0, 0, 0, 60, // TTL + 0, addrlen}; + memcpy(dest, recordstart, sizeof(recordstart)); + if(qtype==QType::A) + memcpy(dest+sizeof(recordstart), &d_a.sin4.sin_addr.s_addr, 4); + else + memcpy(dest+sizeof(recordstart), &d_aaaa.sin6.sin6_addr.s6_addr, 16); + len = (dest + sizeof(recordstart) + addrlen) - (char*)dh; + return Action::HeaderModify; + } + string toString() const override + { + string ret; + if(d_a.sin4.sin_family) + ret="spoof in "+d_a.toString(); + if(d_aaaa.sin6.sin6_family) { + if(!ret.empty()) ret += ", "; + ret+="spoof in "+d_aaaa.toString(); + } + return ret; + } +private: + ComboAddress d_a; + ComboAddress d_aaaa; +}; + + class NoRecurseAction : public DNSAction { public: - DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, int len, string* ruleresult) const override + DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, uint16_t& len, string* ruleresult) const override { dh->rd = false; return Action::HeaderModify; @@ -283,7 +336,7 @@ public: class DisableValidationAction : public DNSAction { public: - DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, int len, string* ruleresult) const override + DNSAction::Action operator()(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh, uint16_t& len, string* ruleresult) const override { dh->cd = true; return Action::HeaderModify; -- 2.40.0