]> granicus.if.org Git - pdns/commitdiff
new function: addDomainSpoof("domain", "ipv4", "ipv6"). Also, DNSActions can now...
authorbert hubert <bert.hubert@netherlabs.nl>
Thu, 10 Dec 2015 11:55:09 +0000 (12:55 +0100)
committerbert hubert <bert.hubert@netherlabs.nl>
Thu, 10 Dec 2015 11:55:09 +0000 (12:55 +0100)
pdns/dnsdist-ecs.cc
pdns/dnsdist-ecs.hh
pdns/dnsdist-lua.cc
pdns/dnsdist-tcp.cc
pdns/dnsdist.cc
pdns/dnsdist.hh
pdns/dnsrulactions.hh

index b0d5e2e6a740611bb3d6146debf20372509706cd..91ac2a9924ba19354e6de32678ecf2f8de776af2 100644 (file)
@@ -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);
index 4edbac7f0d0fda12baac41424db8d22c9a1f3322..74138fdda6485c455a72e693e77c41dfa5c40b62 100644 (file)
@@ -2,7 +2,7 @@
 
 int rewriteResponseWithoutEDNS(const char * packet, size_t len, vector<uint8_t>& 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);
 
 
 
index 772e1071904f1cb25449463ca4745eab8373439c..45a8d0c70b01009e31ebd4a350bddc063b800580 100644 (file)
@@ -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<std::function<void(void)>> setupLua(bool client, const std::string& confi
       {"Pool", (int)DNSAction::Action::Pool}, 
       {"None",(int)DNSAction::Action::Pool}}
     );
-
   
   g_lua.writeFunction("newServer", 
                      [client](boost::variant<string,newserver_t> pvars, boost::optional<int> qps)
@@ -400,6 +399,37 @@ vector<std::function<void(void)>> setupLua(bool client, const std::string& confi
       return std::shared_ptr<DNSAction>(new NoRecurseAction);
     });
 
+  g_lua.writeFunction("SpoofAction", [](const string& a, boost::optional<string> b) {
+      if(b) 
+       return std::shared_ptr<DNSAction>(new SpoofAction(ComboAddress(a), ComboAddress(*b)));
+      else 
+       return std::shared_ptr<DNSAction>(new SpoofAction(ComboAddress(a)));
+    });
+
+  g_lua.writeFunction("addDomainSpoof", [](const std::string& domain, const std::string& ip, boost::optional<string> 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<SuffixMatchNodeRule>(smn), 
+               std::make_shared<SpoofAction>(a, b)  });
+       });
+
+    });
+
+
   g_lua.writeFunction("DropAction", []() {
       return std::shared_ptr<DNSAction>(new DropAction);
     });
index 77e63045bbb4900adb929e096025257f81fc8e92..a92820c963fa93b6c0770f09abd2c0c12e629812 100644 (file)
@@ -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();
index d8080c2371fe76bced020475d078f996faa6cb2b..69ef44e8ab6a5fbfc5d752b17676c71802349e29 100644 (file)
@@ -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)) {
index 115361f7c16628ede5da50524134cb93f1c74ade..597ce1a5ec6f5d1a7c7332851a86bcd3c15c8ed2 100644 (file)
@@ -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;
 };
 
index 5712b774b44009a28b8294522f92a3f5fa773bb0..81375622edfa07c8d0b4a865b6151892d747fd53 100644 (file)
@@ -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;