]> granicus.if.org Git - pdns/commitdiff
tool to blast packets from fake IP addresses even from pcaps without ethernet headers dnssend
authorbert hubert <bert.hubert@powerdns.com>
Thu, 15 Jun 2017 07:53:10 +0000 (09:53 +0200)
committerbert hubert <bert.hubert@powerdns.com>
Thu, 15 Jun 2017 07:53:10 +0000 (09:53 +0200)
pdns/Makefile.am
pdns/dnssend.cc [new file with mode: 0644]

index 8d8b509ec9956e79c459ef0530b6f07cf28f4806..b57eb9e0714af1bd5acd192d04ed53b398235b4c 100644 (file)
@@ -80,6 +80,7 @@ bin_PROGRAMS = \
 if TOOLS
 bin_PROGRAMS += \
        dnsgram \
+       dnssend \
        dnsreplay \
        dnsscan \
        dnsscope \
@@ -114,6 +115,7 @@ EXTRA_PROGRAMS = \
        dnsreplay \
        dnsscan \
        dnsscope \
+       dnssend \
        dnstcpbench \
        dnswasher \
        dumresp \
@@ -1035,6 +1037,35 @@ dnsgram_LDFLAGS = \
 dnsgram_LDADD = \
        $(LIBCRYPTO_LIBS)
 
+dnssend_SOURCES = \
+       base32.cc \
+       base64.cc base64.hh \
+       dnssend.cc \
+       dnslabeltext.cc \
+       dnsname.cc dnsname.hh \
+       dnsparser.cc dnsparser.hh \
+       dnspcap.cc dnspcap.hh \
+       dnsrecords.cc \
+       dnswriter.cc dnswriter.hh \
+       iputils.cc\
+       logger.cc \
+       misc.cc \
+       nsecrecords.cc \
+       qtype.cc \
+       rcpgenerator.cc rcpgenerator.hh \
+       sillyrecords.cc \
+       statbag.cc \
+       unix_utility.cc \
+       utility.hh
+
+dnssend_LDFLAGS = \
+       $(AM_LDFLAGS) \
+       $(LIBCRYPTO_LDFLAGS)
+
+dnssend_LDADD = \
+       $(LIBCRYPTO_LIBS)
+
+
 dnsdemog_SOURCES = \
        base32.cc \
        base64.cc base64.hh \
diff --git a/pdns/dnssend.cc b/pdns/dnssend.cc
new file mode 100644 (file)
index 0000000..ef55f80
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#define __FAVOR_BSD
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "statbag.hh"
+#include "dnspcap.hh"
+#include "dnsrecords.hh"
+#include "dnsparser.hh"
+#include <boost/tuple/tuple.hpp>
+#include <boost/tuple/tuple_comparison.hpp>
+#include <map>
+#include <set>
+#include <fstream>
+#include <algorithm>
+#include "anadns.hh"
+
+#include "namespaces.hh"
+#include "namespaces.hh"
+
+StatBag S;
+
+struct tm* pdns_localtime_r(const uint32_t* then, struct tm* tm)
+{
+  time_t t = *then;
+  
+  return localtime_r(&t, tm);
+}
+
+int32_t g_clientQuestions, g_clientResponses, g_serverQuestions, g_serverResponses, g_skipped;
+struct pdns_timeval g_lastanswerTime, g_lastquestionTime;
+void makeReport(const struct pdns_timeval& tv)
+{
+  int64_t clientdiff = g_clientQuestions - g_clientResponses;
+  int64_t serverdiff = g_serverQuestions - g_serverResponses;
+
+  if(clientdiff > 1 && clientdiff > 0.02*g_clientQuestions) {
+    char tmp[80];
+    struct tm tm=*pdns_localtime_r(&tv.tv_sec, &tm);
+    strftime(tmp, sizeof(tmp) - 1, "%F %H:%M:%S", &tm);
+
+    cout << tmp << ": Resolver dropped too many questions (" 
+         << g_clientQuestions <<" vs " << g_clientResponses << "), diff: " <<clientdiff<<endl;
+
+    tm=*pdns_localtime_r(&g_lastanswerTime.tv_sec, &tm);
+    strftime(tmp, sizeof(tmp) - 1, "%F %H:%M:%S", &tm);
+    
+    cout<<"Last answer: "<<tmp<<"."<<g_lastanswerTime.tv_usec/1000000.0<<endl;
+
+    tm=*pdns_localtime_r(&g_lastquestionTime.tv_sec, &tm);
+    strftime(tmp, sizeof(tmp) - 1, "%F %H:%M:%S", &tm);
+    
+    cout<<"Last question: "<<tmp<<"."<<g_lastquestionTime.tv_usec/1000000.0<<endl;
+  }
+
+  if(serverdiff > 1 && serverdiff > 0.02*g_serverQuestions) {
+    char tmp[80];
+    struct tm tm=*pdns_localtime_r(&tv.tv_sec, &tm);
+    strftime(tmp, sizeof(tmp) - 1, "%F %H:%M:%S", &tm);
+
+    cout << tmp << ": Auth server dropped too many questions (" 
+         << g_serverQuestions <<" vs " << g_serverResponses << "), diff: " <<serverdiff<<endl;
+
+    tm=*pdns_localtime_r(&g_lastanswerTime.tv_sec, &tm);
+    strftime(tmp, sizeof(tmp) - 1, "%F %H:%M:%S", &tm);
+    
+    cout<<"Last answer: "<<tmp<<"."<<g_lastanswerTime.tv_usec/1000000.0<<endl;
+
+    tm=*pdns_localtime_r(&g_lastquestionTime.tv_sec, &tm);
+    strftime(tmp, sizeof(tmp) - 1, "%F %H:%M:%S", &tm);
+    
+    cout<<"Last question: "<<tmp<<"."<<g_lastquestionTime.tv_usec/1000000.0<<endl;
+  }
+//  cout <<"Recursive questions: "<<g_clientQuestions<<", recursive responses: " << g_clientResponses<< 
+//    ", server questions: "<<g_serverQuestions<<", server responses: "<<g_serverResponses<<endl;
+
+
+//  cerr << tv.tv_sec << " " <<g_clientQuestions<<" " << g_clientResponses<< " "<<g_serverQuestions<<" "<<g_serverResponses<<" "<<g_skipped<<endl;
+  g_clientQuestions=g_clientResponses=g_serverQuestions=g_serverResponses=0;
+  g_skipped=0;
+}
+
+void usage() {
+  cerr<<"syntax: dnssend INFILE destination usec"<<endl;
+}
+
+int main(int argc, char** argv)
+try
+{
+  // Parse possible options
+  if (argc == 1) {
+    usage();
+    return EXIT_SUCCESS;
+  }
+
+  for(int n=1 ; n < argc; ++n) {
+    if ((string) argv[n] == "--help") {
+      usage();
+      return EXIT_SUCCESS;
+    }
+
+    if ((string) argv[n] == "--version") {
+      cerr<<"dnsgram "<<VERSION<<endl;
+      return EXIT_SUCCESS;
+    }
+  }
+
+  ComboAddress dest(argv[2]);
+  uint32_t snooze=atoi(argv[3]);
+   
+  reportAllTypes();
+  for(int n=1 ; n < 2; ++n) {
+    cout<<argv[n]<<endl;
+    unsigned int parseErrors=0, totalQueries=0, skipped=0;
+    PcapPacketReader pr(argv[n]);
+    //    PcapPacketWriter pw(argv[n]+string(".out"), pr);
+    /* four sorts of packets: 
+       "rd": question from a client pc
+       "rd qr": answer to a client pc
+       "": question from the resolver
+       "qr": answer to the resolver */
+    
+    /* what are interesting events to note? */
+    /* we measure every 60 seconds, each interval with 10% less answers than questions is interesting */
+    /* report chunked */
+    
+
+    int count=0;
+    while(pr.getUDPPacket()) {
+      if((ntohs(pr.d_udp->uh_dport)==5300 || ntohs(pr.d_udp->uh_sport)==5300 ||
+          ntohs(pr.d_udp->uh_dport)==53   || ntohs(pr.d_udp->uh_sport)==53) &&
+         pr.d_len > 12) {
+        try {
+         struct dnsheader *hdr=(struct dnsheader*)pr.d_payload;
+
+          if(!hdr->rd || hdr->qr) 
+           continue;
+
+         int sock=socket(AF_INET, SOCK_DGRAM, 0);
+         SSetsockopt(sock, IPPROTO_IP , IP_TRANSPARENT, 1);
+         SBind(sock, pr.getSource());
+         sendto(sock, pr.d_payload, pr.d_len, 0, (struct sockaddr*)&dest, dest.getSocklen());
+         close(sock);
+         if(!(++count % 1024))
+           usleep(snooze);
+        }
+        catch(std::exception& e) {
+          cerr << e.what() << endl;
+          continue;
+        }
+      }
+    }
+  }
+}
+catch(std::exception& e)
+{
+  cerr<<"Fatal: "<<e.what()<<endl;
+}