From: bert hubert Date: Tue, 16 Dec 2014 09:22:06 +0000 (+0100) Subject: teach dnsdist about regex-drop, for smart packet filtering X-Git-Tag: rec-3.7.0-rc1~109^2~11 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a4652d55a7528262342c9b8d4e636ac19ac5e0e4;p=pdns teach dnsdist about regex-drop, for smart packet filtering --- diff --git a/pdns/Makefile.am b/pdns/Makefile.am index 71442ecbf..a01c1238e 100644 --- a/pdns/Makefile.am +++ b/pdns/Makefile.am @@ -498,8 +498,10 @@ dnstcpbench_LDFLAGS = $(THREADFLAGS) $(BOOST_PROGRAM_OPTIONS_LDFLAGS) dnstcpbench_LDADD = $(BOOST_PROGRAM_OPTIONS_LIBS) dnsdist_SOURCES = \ + arguments.cc \ base32.cc \ base64.cc base64.hh \ + dns.cc \ dnsdist.cc \ dnslabeltext.cc \ dnsparser.cc dnsparser.hh \ diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index e1e9c6c52..f7110078b 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -26,6 +26,7 @@ #include #include #include +#include "arguments.hh" /* syntax: dnsdist 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 Added downstream server 8.8.8.8:53 @@ -37,12 +38,18 @@ And you are in business! */ +ArgvMap& arg() +{ + static ArgvMap a; + return a; +} StatBag S; namespace po = boost::program_options; po::variables_map g_vm; bool g_verbose; AtomicCounter g_pos; +AtomicCounter g_regexBlocks; uint16_t g_maxOutstanding; bool g_console; @@ -167,6 +174,7 @@ static void daemonize(void) // listens to incoming queries, sends out to downstream servers, noting the intended return path void* udpClientThread(void* p) +try { ClientState* cs = (ClientState*) p; @@ -178,11 +186,26 @@ void* udpClientThread(void* p) struct dnsheader* dh = (struct dnsheader*) packet; int len; + string qname; + uint16_t qtype; + + Regex* re=0; + if(g_vm.count("regex-drop")) + re=new Regex(g_vm["regex-drop"].as()); + for(;;) { len = recvfrom(cs->udpFD, packet, sizeof(packet), 0, (struct sockaddr*) &remote, &socklen); - if(len < 0) + if(len < (int)sizeof(struct dnsheader)) continue; + if(re) { + qname=questionExpand(packet, len, qtype); + if(re->match(qname)) { + g_regexBlocks++; + continue; + } + } + /* right now, this is our simple round robin downstream selector */ DownstreamState& ss = getBestDownstream(); ss.queries++; @@ -210,6 +233,21 @@ void* udpClientThread(void* p) } return 0; } +catch(std::exception &e) +{ + errlog("UDP client thread died because of exception: %s", e.what()); + return 0; +} +catch(PDNSException &e) +{ + errlog("UDP client thread died because of PowerDNS exception: %s", e.reason); + return 0; +} +catch(...) +{ + errlog("UDP client thread died because of an exception: %s", "unknown"); + return 0; +} /* TCP: the grand design. We forward 'messages' between clients and downstream servers. Messages are 65k bytes large, tops. @@ -446,12 +484,14 @@ try { signal(SIGPIPE, SIG_IGN); openlog("dnsdist", LOG_PID, LOG_DAEMON); + g_console=true; po::options_description desc("Allowed options"), hidden, alloptions; desc.add_options() ("help,h", "produce help message") ("daemon", po::value()->default_value(true), "run in background") - ("local", po::value >(), "Listen on which address") + ("local", po::value >(), "Listen on which addresses") ("max-outstanding", po::value()->default_value(65535), "maximum outstanding queries per downstream") + ("regex-drop", po::value(), "If set, block queries matching this regex. Mind trailing dot!") ("verbose,v", "be verbose"); hidden.add_options() @@ -479,11 +519,13 @@ try exit(EXIT_FAILURE); } - if(g_vm["daemon"].as()) + if(g_vm["daemon"].as()) { + g_console=false; daemonize(); + } else { infolog("Running in the %s", "foreground"); - g_console=true; + } vector remotes = g_vm["remotes"].as >();