From: bert hubert Date: Mon, 15 Feb 2016 20:20:13 +0000 (+0100) Subject: scanning zonefiles & polling nameservers X-Git-Tag: rec-4.0.0-alpha2~62^2~4 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ca12836d9022f8473814ead3a066020dc9f27bd9;p=pdns scanning zonefiles & polling nameservers --- diff --git a/pdns/Makefile.am b/pdns/Makefile.am index cbd887cd1..608df51b7 100644 --- a/pdns/Makefile.am +++ b/pdns/Makefile.am @@ -96,6 +96,7 @@ endif EXTRA_PROGRAMS = \ calidns \ + comfun \ dnsbulktest \ dnsdemog \ dnsgram \ @@ -771,6 +772,37 @@ dnsbulktest_LDADD = \ $(OPENSSL_LIBS) \ $(BOOST_PROGRAM_OPTIONS_LIBS) +comfun_SOURCES = \ + base32.cc \ + base64.cc \ + comfun.cc \ + dns.cc \ + dnslabeltext.cc \ + dnsname.cc dnsname.hh \ + dnsparser.cc \ + dnsrecords.cc \ + dnswriter.cc \ + logger.cc \ + misc.cc \ + nsecrecords.cc \ + qtype.cc \ + rcpgenerator.cc \ + sillyrecords.cc \ + statbag.cc \ + unix_utility.cc \ + zoneparser-tng.cc zoneparser-tng.hh + +comfun_LDFLAGS = \ + $(AM_LDFLAGS) \ + $(OPENSSL_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) + +comfun_LDADD = \ + $(MBEDTLS_LIBS) \ + $(OPENSSL_LIBS) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) + + dnsscan_SOURCES = \ anadns.hh \ base32.cc \ diff --git a/pdns/comfun.cc b/pdns/comfun.cc new file mode 100644 index 000000000..a4e5e39bf --- /dev/null +++ b/pdns/comfun.cc @@ -0,0 +1,526 @@ +#include "statbag.hh" +#include "zoneparser-tng.hh" +#include "namespaces.hh" +#include "dnsrecords.hh" +#include +#include +#include +#include +#include "inflighter.cc" +//#include "malloctrace.hh" +StatBag S; +bool g_quiet; +std::unique_ptr g_powerdns; +std::atomic g_count; +std::atomic g_stop; + + +struct namecount { + set names; + unsigned int count; + bool isPowerDNS{false}; +}; + +struct DNSResult +{ + string content; + int ttl{0}; + uint16_t qclass; +}; + +struct NSQuery +{ + ComboAddress a; + set nsnames; + DNSName qname; + unsigned int count; +}; + +struct SendReceive +{ + typedef int Identifier; + typedef DNSResult Answer; // ip + int d_socket; + deque d_idqueue; + + SendReceive(map& res) : d_res(res) + { + d_socket = socket(AF_INET, SOCK_DGRAM, 0); + int val=1; + setsockopt(d_socket, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); + + for(unsigned int id =0 ; id < std::numeric_limits::max(); ++id) + d_idqueue.push_back(id); + } + + ~SendReceive() + { + close(d_socket); + } + + Identifier send(NSQuery& domain) + { + //cerr<<"Sending query for '"< packet; + + DNSPacketWriter pw(packet, domain.qname, QType::TXT, 3); + + if(d_idqueue.empty()) { + cerr<<"Exhausted ids!"<id = d_idqueue.front(); + d_idqueue.pop_front(); + pw.getHeader()->rd = 0; + pw.getHeader()->qr = 0; + + if(::sendto(d_socket, &*packet.begin(), packet.size(), 0, (struct sockaddr*)&domain.a, domain.a.getSocklen()) < 0) + d_senderrors++; + + return pw.getHeader()->id; + } + + bool receive(Identifier& id, DNSResult& dr) + { + if(waitForData(d_socket, 0, 500000) > 0) { + char buf[512]; + ComboAddress from; + from.sin4.sin_family = AF_INET; + socklen_t socklen=from.getSocklen(); + int len = recvfrom(d_socket, buf, sizeof(buf),0, (struct sockaddr*)&from, &socklen); + if(len < 0) { + d_receiveerrors++; + return 0; + } + else { + d_receiveds++; + } + // parse packet, set 'id', fill out 'ip' + + MOADNSParser mdp(string(buf, len)); + if(!g_quiet) { + cout<<"Reply to question for qname='"<getZoneRepresentation(); + dr.ttl=a.first.d_ttl; + } + } + if(dr.content.empty()) + dr.content="RCode: "+RCode::to_s(mdp.d_header.rcode); + return 1; + } + return 0; + } + + void deliverTimeout(const Identifier& id) + { + if(!g_quiet) { + cout<<"Timeout for id "<second.isPowerDNS) { + (*g_powerdns)<second.isPowerDNS=true; + } + + } + + } + unsigned int d_errors, d_nxdomains, d_nodatas, d_oks, d_unknowns; + unsigned int d_receiveds, d_receiveerrors, d_senderrors; + map& d_res; +}; + + +struct RESResult +{ + vector addrs; + uint16_t rcode; +}; + +typedef DNSName RESQuery; + +struct SendReceiveRes +{ + typedef int Identifier; + typedef RESResult Answer; // ip + int d_socket; + deque d_idqueue; + map>& d_out; + SendReceiveRes(const ComboAddress& remote, map>& out) : d_out(out) + { + d_socket = socket(AF_INET, SOCK_DGRAM, 0); + int val=1; + setsockopt(d_socket, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); + connect(d_socket, (struct sockaddr*)&remote, remote.getSocklen()); + for(unsigned int id =0 ; id < std::numeric_limits::max(); ++id) + d_idqueue.push_back(id); + } + + ~SendReceiveRes() + { + close(d_socket); + } + + Identifier send(RESQuery& domain) + { + //cerr<<"Sending query for '"< packet; + + DNSPacketWriter pw(packet, domain, QType::A); + + if(d_idqueue.empty()) { + cerr<<"Exhausted ids!"<id = d_idqueue.front(); + d_idqueue.pop_front(); + pw.getHeader()->rd = 1; + pw.getHeader()->qr = 0; + + if(::send(d_socket, &*packet.begin(), packet.size(), 0) < 0) { + cout<<"Error sending: "<id; + } + + bool receive(Identifier& id, RESResult& dr) + { + if(waitForData(d_socket, 0, 500000) > 0) { + char buf[512]; + ComboAddress from; + from.sin4.sin_family = AF_INET; + socklen_t socklen=from.getSocklen(); + int len = recvfrom(d_socket, buf, sizeof(buf),0, (struct sockaddr*)&from, &socklen); + if(len < 0) { + d_receiveerrors++; + return 0; + } + else { + d_receiveds++; + } + // parse packet, set 'id', fill out 'ip' + + MOADNSParser mdp(string(buf, len)); + if(!g_quiet) { + cout<<"Reply to question for qname='"<getZoneRepresentation()< nsnames; + map > addresses; + + + while(zpt.get(rr)) { + if(rr.qtype.getCode() == QType::NS) + nsnames[DNSName(rr.content)]++; + else if(rr.qtype.getCode() == QType::A || rr.qtype.getCode() == QType::AAAA) { + DNSRecord dr(rr); + addresses[rr.qname].insert(getAddr(dr, 53)); + } + ++g_count; + if(g_count == limit) + break; + } + g_stop=true; + stats.join(); + + cout<<"Got "< tores; + while(getline(needres,line)) { + tores.push_back(DNSName(line)); + } + cerr<<"Going to resolve "<> output; + SendReceiveRes sr(ComboAddress("192.168.1.2", 53), output); + Inflighter, SendReceiveRes> inflighter(tores, sr); + inflighter.d_maxInFlight = 1000; + inflighter.d_timeoutSeconds = 3; + inflighter.d_burst = 100; + for(;;) { + try { + inflighter.run(); + break; + } + catch(std::exception& e) { + cerr<<"Caught exception: "<>& addrs) +{ + ifstream ifs(fname); + if(!ifs) + unixDie("Reading resolved names from "+fname+": "+string(strerror(errno))); + vector parts; + string line; + addrs.clear(); + while(getline(ifs, line)) { + parts.clear(); + stringtok(parts, line,"\t"); + for(unsigned int n=2; n < parts.size(); ++n) + addrs[DNSName(parts[0])].push_back(ComboAddress(parts[n], 53)); + } + //EARTH.DOMAINS.SHELTEK.CA. 0 67.15.253.219 67.15.47.188 67.15.253.252 67.15.253.251 67.15.47.189 67.15.253.220 + cerr<<"Got "< 3) + limit = atoi(argv[3]); + + return parseZone(argv[2], limit); + } + else if(mode=="resolve-ns") { + return resolveNS(string(argv[2])+".needres"); + } + else if(mode=="scan-ns") { + ifstream ns(string(argv[2])+".nameservers"); + g_powerdns = make_unique(string(argv[2])+".powerdns"); + string line; + int count=0; + vector parts; + + struct NSCount + { + unsigned int count{0}; + vector addrs; + }; + map stats; + NSCount nscount; + // NS1.IHOST2000.COM. 9 162.251.82.122 162.251.82.123 162.251.82.250 162.251.82.251 + while(getline(ns, line)) { + ++count; + parts.clear(); + stringtok(parts, line,"\t"); + nscount.count=atoi(parts[1].c_str()); + nscount.addrs.clear(); + for(unsigned int n = 2; n < parts.size(); ++n) + nscount.addrs.push_back(ComboAddress(parts[n], 53)); + stats.insert({DNSName(parts[0]), nscount}); + } + cerr<<"Had "<> lookedup; + readRESNames(argv[2]+string(".resolved"), lookedup); + + map pure; + + unsigned int noaddrs=0; + for(const auto& s : stats) { + auto ptr = &s.second.addrs; + if(ptr->empty()) { + if(lookedup.count(s.first)) { + ptr = &lookedup[s.first]; + } + else { + //cout<<"Have no address for "< domains; + + Inflighter, SendReceive> inflighter(domains, sr); + inflighter.d_maxInFlight = 1000; + inflighter.d_timeoutSeconds = 3; + inflighter.d_burst = 100; + + for(const auto& p : pure) { + NSQuery nsq; + nsq.a=p.first; + nsq.nsnames = p.second.names; + nsq.count = p.second.count; + + nsq.qname=DNSName("version.bind"); + domains.push_back(nsq); + nsq.qname=DNSName("id.server"); + domains.push_back(nsq); + nsq.qname=DNSName("bind.version"); + domains.push_back(nsq); + } + + sort(domains.begin(), domains.end(), [](const NSQuery& a, const NSQuery& b) { return b.count < a.count; }); + for(;;) { + try { + inflighter.run(); + break; + } + catch(std::exception& e) { + cerr<<"Caught exception: "< powerdns; + ifstream ifs(string(argv[2])+".powerdns"); + string line; + vector parts; + while(getline(ifs,line)) { + // 64.96.240.53 1234 NS1.UNIREGISTRYMARKET.LINK. NS1.INTERNETTRAFFIC.COM. BUY.INTERNETTRAFFIC.COM. NS3.SECUREDOFFERS.COM. NS3.GI.NET. NS3.IT.GI.NET. NS3.EASILY.NET. + parts.clear(); + stringtok(parts, line); + for(unsigned int n=2; n < parts.size(); ++n) + powerdns.insert(DNSName(parts[n])); + } + cerr<<"Have "< seen, pdnsdomains; + int count=0; + while(zpt.get(rr)) { + if(!seen.count(rr.qname)) { + seen.insert(rr.qname); + } + if(rr.qtype.getCode() == QType::NS && powerdns.count(DNSName(rr.content)) && !pdnsdomains.count(DNSName(rr.qname))) { + pdnscount++; + pdnsdomains.insert(DNSName(rr.qname)); + } + if(!(count%100000)) { + cerr<<"\rUnique domains: "<topAllocatorsString(20)<(&e.second)) - obj.insert({e.first, (int)(*val)->load()}); + obj.insert({e.first, (double)(*val)->load()}); else if (const auto& val = boost::get(&e.second)) obj.insert({e.first, (**val)}); else diff --git a/pdns/dnsname.hh b/pdns/dnsname.hh index 7c9326e08..5c49c525f 100644 --- a/pdns/dnsname.hh +++ b/pdns/dnsname.hh @@ -5,7 +5,7 @@ #include #include #include -// #include +#include uint32_t burtleCI(const unsigned char* k, uint32_t lengh, uint32_t init); @@ -96,8 +96,8 @@ public: inline bool canonCompare(const DNSName& rhs) const; bool slowCanonCompare(const DNSName& rhs) const; private: - // typedef boost::container::string string_t; - typedef std::string string_t; + typedef boost::container::string string_t; + // typedef std::string string_t; string_t d_storage; diff --git a/pdns/test-iputils_hh.cc b/pdns/test-iputils_hh.cc index 9505fd696..a1afbc7be 100644 --- a/pdns/test-iputils_hh.cc +++ b/pdns/test-iputils_hh.cc @@ -134,8 +134,17 @@ BOOST_AUTO_TEST_CASE(test_ComboAddressTruncate) { BOOST_CHECK_EQUAL(result, manual); } +} + +BOOST_AUTO_TEST_CASE(test_Mapping) +{ + ComboAddress lh("::1"); + BOOST_CHECK_EQUAL(lh.toString(), "::1"); + ComboAddress lh2("::2"); + BOOST_CHECK_EQUAL(lh2.toString(), "::2"); + } BOOST_AUTO_TEST_CASE(test_Netmask) {