From 152b0801dc0884fc67a6bd0764e1045e1e8b6fb2 Mon Sep 17 00:00:00 2001 From: bert hubert Date: Fri, 16 Feb 2018 10:03:39 +0100 Subject: [PATCH] made dnswasher support ipcipher --- pdns/Makefile.am | 4 ++ pdns/dnswasher.cc | 157 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 136 insertions(+), 25 deletions(-) diff --git a/pdns/Makefile.am b/pdns/Makefile.am index 23a71deeb..acfc9d5c7 100644 --- a/pdns/Makefile.am +++ b/pdns/Makefile.am @@ -881,18 +881,22 @@ speedtest_LDADD = $(LIBCRYPTO_LIBS) \ $(RT_LIBS) dnswasher_SOURCES = \ + base64.cc \ dnslabeltext.cc \ dnsname.hh dnsname.cc \ dnsparser.hh \ dnspcap.cc dnspcap.hh \ dnswasher.cc \ dnswriter.hh \ + ipcipher.cc ipcipher.hh ../ext/ipcrypt/ipcrypt.c ../ext/ipcrypt/ipcrypt.h \ logger.cc \ misc.cc \ qtype.cc \ statbag.cc \ unix_utility.cc +dnswasher_LDFLAGS = $(AM_LDFLAGS) $(BOOST_PROGRAM_OPTIONS_LDFLAGS) $(LIBCRYPTO_LDFLAGS) +dnswasher_LDADD = $(BOOST_PROGRAM_OPTIONS_LIBS) $(LIBCRYPTO_LIBS) dnsbulktest_SOURCES = \ base32.cc \ diff --git a/pdns/dnswasher.cc b/pdns/dnswasher.cc index c105f3bea..0f81c385b 100644 --- a/pdns/dnswasher.cc +++ b/pdns/dnswasher.cc @@ -40,19 +40,40 @@ otherwise, obfuscate the response IP address #include "statbag.hh" #include "dnspcap.hh" #include "iputils.hh" - +#include "ipcipher.hh" #include "namespaces.hh" +#include +#include "base64.hh" StatBag S; +namespace po = boost::program_options; +po::variables_map g_vm; + + class IPObfuscator { public: - IPObfuscator() : d_romap(d_ipmap), d_ro6map(d_ip6map), d_counter(0) + virtual uint32_t obf4(uint32_t orig)=0; + virtual struct in6_addr obf6(const struct in6_addr& orig)=0; +}; + +class IPSeqObfuscator : public IPObfuscator +{ +public: + IPSeqObfuscator() : d_romap(d_ipmap), d_ro6map(d_ip6map), d_counter(0) { } - uint32_t obf4(uint32_t orig) + ~IPSeqObfuscator() + {} + + static std::unique_ptr make() + { + return std::unique_ptr(new IPSeqObfuscator()); + } + + uint32_t obf4(uint32_t orig) override { if(d_romap.count(orig)) return d_ipmap[orig]; @@ -61,7 +82,7 @@ public: } } - struct in6_addr obf6(const struct in6_addr& orig) + struct in6_addr obf6(const struct in6_addr& orig) override { uint32_t val; if(d_ro6map.count(orig)) @@ -95,6 +116,48 @@ private: uint32_t d_counter; }; +class IPCipherObfuscator : public IPObfuscator +{ +public: + IPCipherObfuscator(const std::string& key, bool decrypt) : d_key(key), d_decrypt(decrypt) + { + if(d_key.size()!=16) { + throw std::runtime_error("IPCipher requires a 128 bit key"); + } + } + + ~IPCipherObfuscator() + {} + static std::unique_ptr make(std::string key, bool decrypt) + { + return std::unique_ptr(new IPCipherObfuscator(key, decrypt)); + } + + uint32_t obf4(uint32_t orig) override + { + ComboAddress ca; + ca.sin4.sin_family = AF_INET; + ca.sin4.sin_addr.s_addr = orig; + ca = d_decrypt ? decryptCA(ca, d_key) : encryptCA(ca, d_key); + return ca.sin4.sin_addr.s_addr; + + } + + struct in6_addr obf6(const struct in6_addr& orig) override + { + ComboAddress ca; + ca.sin4.sin_family = AF_INET6; + ca.sin6.sin6_addr = orig; + ca = d_decrypt ? decryptCA(ca, d_key) : encryptCA(ca, d_key); + return ca.sin6.sin6_addr; + } + +private: + std::string d_key; + bool d_decrypt; +}; + + void usage() { cerr<<"Syntax: dnswasher INFILE1 [INFILE2..] OUTFILE"<(), "base64 encoded 128 bit key for ipcipher") + ("passphrase,p", po::value(), "passphrase for ipcipher (will be used to derive key)") + ("decrypt,d", "decrypt IP addresses with ipcipher"); + + po::options_description alloptions; + po::options_description hidden("hidden options"); + hidden.add_options() + ("infiles", po::value>(), "PCAP source file(s)") + ("outfile", po::value(), "outfile"); - if ((string) argv[i] == "--version") { - cerr<<"dnswasher "<()); + std::unique_ptr ipo; + + if(!g_vm.count("key") && !g_vm.count("passphrase")) + ipo = IPSeqObfuscator::make(); + else if(g_vm.count("key") && !g_vm.count("passphrase")) { + string key; + if(B64Decode(g_vm["key"].as(), key) < 0) { + cerr<<"Invalidly encoded base64 key provided"<()); + + ipo = IPCipherObfuscator::make(key, doDecrypt); + } + else { + cerr<<"Can't specify both 'key' and 'passphrase'"<>()) { + PcapPacketReader pr(inf); pw.setPPR(pr); while(pr.getUDPPacket()) { @@ -136,9 +243,9 @@ try uint32_t *dst=(uint32_t*)&pr.d_ip->ip_dst; if(dh->qr) - *dst=htonl(ipo.obf4(*dst)); + *dst=ipo->obf4(*dst); else - *src=htonl(ipo.obf4(*src)); + *src=ipo->obf4(*src); pr.d_ip->ip_sum=0; } else if (pr.d_ip->ip_v == 6) { @@ -146,9 +253,9 @@ try auto dst=&pr.d_ip6->ip6_dst; if(dh->qr) - *dst=ipo.obf6(*dst); + *dst=ipo->obf6(*dst); else - *src=ipo.obf6(*src); + *src=ipo->obf6(*src); // IPv6 checksum does not cover source/destination addresses } pw.write(); -- 2.40.0