]> granicus.if.org Git - pdns/commitdiff
implement stunningly cool spoofing protection, plus spoofer in dnspbench
authorBert Hubert <bert.hubert@netherlabs.nl>
Fri, 14 Apr 2006 11:26:50 +0000 (11:26 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Fri, 14 Apr 2006 11:26:50 +0000 (11:26 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@699 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/dnsparser.cc
pdns/dnspbench.cc
pdns/dnswriter.cc
pdns/mtasker.cc
pdns/mtasker.hh
pdns/pdns_recursor.cc
pdns/rcpgenerator.cc
pdns/syncres.hh

index 6f432e29d3d8bef263315f8732e29036d027977a..90c2abce8ac0284650967f03146f73a874a1f016 100644 (file)
@@ -378,6 +378,7 @@ void PacketReader::getLabelFromContent(const vector<uint8_t>& content, uint16_t&
       return getLabelFromContent(content, offset, ret, ++recurs);
     }
     else {
+      // should check for . here and replace by \.
       ret.append(&content.at(frompos), &content.at(frompos+labellen));
       ret.append(1,'.');
       frompos+=labellen;
index c0af89a8f7b4b8e43c09171366ec38b6945284da..bf164dc351e754d7e84702164c1c2bafcc6f288e 100644 (file)
@@ -44,27 +44,32 @@ try
 {
   reportAllTypes();
 
-#if 0
   Socket s(InterNetwork, Datagram);
+  
+  IPEndpoint rem("127.0.0.1",1232), loc("213.156.2.1", 53);
+  s.bind(loc);
 
   vector<uint8_t> vpacket;
-  string domain="www.ds9a.nl";
+  string domain="ds9a.nl";
   uint16_t type=1;
 
-  for(unsigned int n=0; n < 1000000; ++n) {
+  for(unsigned int n=0; n < 65536; ++n) {
     DNSPacketWriter pw(vpacket, domain, type);
     
     pw.getHeader()->rd=1;
+    pw.getHeader()->qr=1;
     pw.getHeader()->id=n;
+    ARecordContent arc("1.2.3.4");
+    pw.startRecord("ds9a.nl", 1, 9999, 1, DNSPacketWriter::ANSWER);
+    arc.toPacket(pw);
     pw.commit();
-    IPEndpoint rem("127.0.0.1",5300);
+
     string spacket((char*)(&*vpacket.begin()), vpacket.size());
     s.sendTo(spacket, rem);
   }
 
-
   return 0; 
-#endif
+#if 0
 
   vector<uint8_t> packet;
 
@@ -82,6 +87,7 @@ try
 
   shared_ptr<DNSRecordContent> regen=DNSRecordContent::unserialize(argv[1], type, record);
   cerr<<"Out: "<<argv[1]<<" IN "<<argv[2]<<" "<<regen->getZoneRepresentation()<<endl;
+#endif
 }
 catch(exception& e)
 {
index f696e985c4650497ad7c1ce6f26abcab393269f9..226fa8a2464e4b6d25b1bca9b1464decf89a6097 100644 (file)
@@ -123,7 +123,7 @@ void DNSPacketWriter::xfrLabel(const string& label, bool compress)
 {
   typedef vector<pair<unsigned int, unsigned int> > parts_t;
   parts_t parts;
-  vstringtok(parts, label, ".");
+  vstringtok(parts, label, "."); // XXX FIXME this should deal with escaped .
   
   // d_stuff is amount of stuff that is yet to be written out - the dnsrecordheader for example
   unsigned int pos=d_content.size() + d_record.size() + d_stuff; 
index 8a815378b74c36f4588c49a10528622dc3bd359f..80fd3bab770c2be7cdd491c36c1060897fde2056 100644 (file)
@@ -158,7 +158,7 @@ int main()
     \return returns -1 in case of error, 0 in case of timeout, 1 in case of an answer 
 */
 
-template<class EventKey, class EventVal>int MTasker<EventKey,EventVal>::waitEvent(const EventKey &key, EventVal *val, unsigned int timeout)
+template<class EventKey, class EventVal>int MTasker<EventKey,EventVal>::waitEvent(EventKey &key, EventVal *val, unsigned int timeout)
 {
   if(d_waiters.count(key)) { // there was already an exact same waiter
     return -1;
@@ -180,6 +180,7 @@ template<class EventKey, class EventVal>int MTasker<EventKey,EventVal>::waitEven
   if(val && d_waitstatus==Answer) 
     *val=d_waitval;
   d_tid=w.tid;
+  key=d_eventkey;
   return d_waitstatus;
 }
 
@@ -216,7 +217,7 @@ template<class EventKey, class EventVal>int MTasker<EventKey,EventVal>::sendEven
   
   ucontext_t *userspace=waiter->context;
   d_tid=waiter->tid;         // set tid 
-  
+  d_eventkey=waiter->key;        // pass waitEvent the exact key it was woken for
   d_waiters.erase(waiter);             // removes the waitpoint 
   if(swapcontext(&d_kernel,userspace)) { // swaps back to the above point 'A'
     perror("swapcontext in sendEvent");
index 5d15189078957bed3707ad1b8bdbb6e683a87590..ba358b2f3ed698e4c8e06aeba2f2407edbdbcedc 100644 (file)
@@ -50,6 +50,17 @@ private:
   std::queue<int> d_runQueue;
   std::queue<int> d_zombiesQueue;
 
+
+  typedef std::map<int, ucontext_t*> mthreads_t;
+  mthreads_t d_threads;
+  int d_tid;
+  int d_maxtid;
+  size_t d_stacksize;
+
+  EventVal d_waitval;
+  enum {Error=-1,TimeOut=0,Answer} d_waitstatus;
+
+public:
   struct Waiter
   {
     EventKey key;
@@ -58,8 +69,6 @@ private:
     int tid;
   };
 
-  //  typedef std::map<EventKey,Waiter> waiters_t;
-
   typedef multi_index_container<
     Waiter,
     indexed_by <
@@ -70,16 +79,6 @@ private:
 
   waiters_t d_waiters;
 
-  typedef std::map<int, ucontext_t*> mthreads_t;
-  mthreads_t d_threads;
-  int d_tid;
-  int d_maxtid;
-  size_t d_stacksize;
-
-  EventVal d_waitval;
-  enum {Error=-1,TimeOut=0,Answer} d_waitstatus;
-
-public:
   //! Constructor
   /** Constructor with a small default stacksize. If any of your threads exceeds this stack, your application will crash. 
       This limit applies solely to the stack, the heap is not limited in any way. If threads need to allocate a lot of data,
@@ -91,7 +90,7 @@ public:
   }
 
   typedef void tfunc_t(void *); //!< type of the pointer that starts a thread 
-  int waitEvent(const EventKey &key, EventVal *val=0, unsigned int timeout=0);
+  int waitEvent(EventKey &key, EventVal *val=0, unsigned int timeout=0);
   void yield();
   int sendEvent(const EventKey& key, const EventVal* val=0);
   void getEvents(std::vector<EventKey>& events);
@@ -103,6 +102,7 @@ public:
 
 private:
   static void threadWrapper(MTasker *self, tfunc_t *tf, int tid, void* val);
+  EventKey d_eventkey;   // for waitEvent, contains exact key it was awoken for
 };
 #include "mtasker.cc"
 
index 934bc6af656ea5019f9c4c036733760ebf08509c..95cde053238cfe5b18d9694b8f6ecffda36acaf5 100644 (file)
@@ -127,7 +127,8 @@ static tcpserversocks_t s_tcpserversocks;
 
 static map<int,PacketID> d_tcpclientreadsocks, d_tcpclientwritesocks;
 
-MTasker<PacketID,string>* MT;
+typedef MTasker<PacketID,string> MT_t;
+MT_t* MT;
 
 int asendtcp(const string& data, Socket* sock) 
 {
@@ -182,6 +183,10 @@ int arecvfrom(char *data, int len, int flags, struct sockaddr *toaddr, Utility::
   if(ret > 0) {
     *d_len=packet.size();
     memcpy(data,packet.c_str(),min(len,*d_len));
+    if(pident.nearMisses > 100) {
+      L<<Logger::Error<<"Too many ("<<pident.nearMisses<<") bogus answers came in from "<<sockAddrToString((struct sockaddr_in*)toaddr, sizeof(pident.remote))<<", assuming spoof attempt."<<endl;
+      return -1;
+    }
   }
   return ret;
 }
@@ -999,6 +1004,12 @@ int main(int argc, char **argv)
                  if(logCommonErrors)
                    L<<Logger::Warning<<"Discarding unexpected packet from "<<sockAddrToString((struct sockaddr_in*) &fromaddr, addrlen)<<endl;
                  g_stats.unexpectedCount++;
+                 
+                 for(MT_t::waiters_t::iterator mthread=MT->d_waiters.begin(); mthread!=MT->d_waiters.end(); ++mthread) {
+                   if(!memcmp(&mthread->key.remote.sin_addr, &pident.remote.sin_addr, sizeof(pident.remote.sin_addr))) {
+                     mthread->key.nearMisses++;
+                   }
+                 }
                }
              }
              else 
index 1c7106b2e11229a451f41977ccbf8fc092ee0bec..5148f9314177b75480759be05bdacea13e3263c6 100644 (file)
@@ -97,8 +97,7 @@ void RecordTextReader::xfr8BitInt(uint8_t &val)
     throw RecordTextException("Overflow reading 8 bit integer from record content"); // fixme improve
 }
 
-
-void RecordTextReader::xfrLabel(string& val, bool)
+void RecordTextReader::xfrLabel(string& val, bool) 
 {
   skipSpaces();
   val.clear();
index 391a4efa402cfdd62004992d744af08cd1d2f307..e224db35847c9be0aaa39aaaae48967e58eeab55 100644 (file)
@@ -317,7 +317,7 @@ int arecvtcp(string& data, int len, Socket* sock);
 
 struct PacketID
 {
-  PacketID() : sock(0), inNeeded(0), outPos(0)
+  PacketID() : sock(0), inNeeded(0), outPos(0), nearMisses(0)
   {}
 
   uint16_t id;  // wait for a specific id/remote pair
@@ -330,6 +330,8 @@ struct PacketID
   string outMSG; // the outgoing message that needs to be sent
   string::size_type outPos;    // how far we are along in the outMSG
 
+  mutable uint32_t nearMisses; // number of near misses - host correct, id wrong
+
   bool operator<(const PacketID& b) const
   {
     int ourSock= sock ? sock->getHandle() : 0;