]> granicus.if.org Git - pdns/commitdiff
very simple DoS database bypass whereby powerdns becomes packetcache only when the...
authorBert Hubert <bert.hubert@netherlabs.nl>
Sun, 19 Jun 2011 22:04:55 +0000 (22:04 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Sun, 19 Jun 2011 22:04:55 +0000 (22:04 +0000)
enable by setting overload-queue-length to a non-zero value (like maybe 100)

git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@2217 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/common_startup.cc
pdns/distributor.hh

index 1c6986895dad0138081e059a1c4bb53a8b126854..ae9f6c1c50500b2bfc4e8a1c96efa2608cd3ed8f 100644 (file)
@@ -49,6 +49,7 @@ void declareArguments()
   ::arg().set("local-ipv6","Local IP address to which we bind")="";
   ::arg().set("query-local-address","Source IP address for sending queries")="0.0.0.0";
   ::arg().set("query-local-address6","Source IPv6 address for sending queries")="::";
+  ::arg().set("overload-queue-length","Maximum queuelength moving to packetcache only")="0";
   ::arg().set("max-queue-length","Maximum queuelength before considering situation lost")="5000";
   ::arg().set("soa-serial-offset","Make sure that no SOA serial is less than this number")="0";
   
@@ -280,8 +281,16 @@ void *qthread(void *number)
 
       continue;
     }
-    if(logDNSQueries)
-        L<<"packetcache MISS"<<endl;
+    
+    if(g_distributor->isOverloaded()) {
+      if(logDNSQueries) 
+        L<<"Dropped query, db is overloaded"<<endl;
+      continue;
+    }
+        
+    if(logDNSQueries) 
+      L<<"packetcache MISS"<<endl;
+
     if(g_mustlockdistributor) {
       Lock l(&d_distributorlock);
       g_distributor->question(P, &sendout); // otherwise, give to the distributor
index cd1f4e45ec3b6c2ed4deafb87117327867d1340b..a339aeec2870505efc347135572513b373b12c18 100644 (file)
@@ -1,6 +1,6 @@
 /*
     PowerDNS Versatile Database Driven Nameserver
-    Copyright (C) 2002  PowerDNS.COM BV
+    Copyright (C) 2002 - 2011  PowerDNS.COM BV
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License version 2
@@ -72,8 +72,6 @@ public:
   static void* makeThread(void *); //!< helper function to create our n threads
   void getQueueSizes(int &questions, int &answers); //!< Returns length of question queue
 
-
-
   int getNumBusy()
   {
     return d_num_threads-d_idle_threads;
@@ -87,11 +85,15 @@ public:
   };
 
   typedef pair<QuestionData, AnswerData> tuple_t;
+  bool isOverloaded()
+  {
+    return d_overloaded;
+  }
   
 private:
+  bool d_overloaded;
   std::queue<QuestionData> questions;
   pthread_mutex_t q_lock;
-
   
   deque<tuple_t> answers;
   pthread_mutex_t a_lock;
@@ -115,6 +117,7 @@ private:
 template<class Answer, class Question, class Backend>Distributor<Answer,Question,Backend>::Distributor(int n)
 {
   b=0;
+  d_overloaded = false;
   nextid=0;
   d_idle_threads=0;
   d_last_started=time(0);
@@ -155,7 +158,7 @@ template<class Answer, class Question, class Backend>void *Distributor<Answer,Qu
     int queuetimeout=::arg().asNum("queue-limit"); 
 #endif 
     // ick ick ick!
-
+    static int overloadQueueLength=::arg().asNum("overload-queue-length");
     for(;;) {
       us->d_idle_threads++;
 
@@ -171,6 +174,10 @@ template<class Answer, class Question, class Backend>void *Distributor<Answer,Qu
       Question *q=QD.Q;
       
       us->questions.pop();
+
+      if(us->d_overloaded && qcount <= overloadQueueLength/10) {
+        us->d_overloaded=false;
+      }
       
       pthread_mutex_unlock(&us->q_lock);
       Answer *a;      
@@ -299,14 +306,21 @@ template<class Answer, class Question, class Backend>int Distributor<Answer,Ques
   pthread_mutex_unlock(&q_lock);
 
   numquestions.post();
+  
+  static int overloadQueueLength=::arg().asNum("overload-queue-length");
 
   if(!(nextid%50)) {
     int val;
     numquestions.getValue( &val );
+    
+    if(!d_overloaded)
+      d_overloaded = overloadQueueLength && (val > overloadQueueLength);
+
     if(val>::arg().asNum("max-queue-length")) {
       L<<Logger::Error<<val<<" questions waiting for database attention. Limit is "<<::arg().asNum("max-queue-length")<<", respawning"<<endl;
       _exit(1);
     }
+
   }
 
   return QD.id;