]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnswasher.cc
Merge pull request #4346 from mind04/anytotcp
[thirdparty/pdns.git] / pdns / dnswasher.cc
1 /*
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23 /** two modes:
24
25 anonymizing and stripping tcpdumps of irrelevant traffic, so operators can send non-privacy violating dumps
26 for analysis.
27
28 algorithm:
29
30 read a packet, check if it has the QR bit set.
31
32 If the question has the response bit set, obfuscate the destination IP address
33 otherwise, obfuscate the response IP address
34 */
35
36
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40 #include "statbag.hh"
41 #include "dnspcap.hh"
42 #include "iputils.hh"
43
44 #include "namespaces.hh"
45
46 StatBag S;
47
48 class IPObfuscator
49 {
50 public:
51 IPObfuscator() : d_romap(d_ipmap), d_ro6map(d_ip6map), d_counter(0)
52 {
53 }
54
55 uint32_t obf4(uint32_t orig)
56 {
57 if(d_romap.count(orig))
58 return d_ipmap[orig];
59 else {
60 return d_ipmap[orig]=d_counter++;
61 }
62 }
63
64 struct in6_addr obf6(const struct in6_addr& orig)
65 {
66 uint32_t val;
67 if(d_ro6map.count(orig))
68 val=d_ip6map[orig];
69 else {
70 val=d_ip6map[orig]=d_counter++;
71 }
72 struct in6_addr ret;
73
74 val=htonl(val);
75 memset(&ret, 0, sizeof(ret));
76 memcpy(((char*)&ret)+12, &val, 4);
77 return ret;
78 }
79
80 private:
81 map<uint32_t, uint32_t> d_ipmap;
82 const decltype(d_ipmap)& d_romap;
83
84 struct cmp {
85 bool operator()(const struct in6_addr&a , const struct in6_addr&b) const
86 {
87 return memcmp(&a, &b, sizeof(a)) < 0;
88 }
89 };
90 // For IPv6 addresses
91 map<struct in6_addr, uint32_t, cmp> d_ip6map;
92 const decltype(d_ip6map)& d_ro6map;
93
94 // The counter that we'll convert to an IP address
95 uint32_t d_counter;
96 };
97
98 void usage() {
99 cerr<<"Syntax: dnswasher INFILE1 [INFILE2..] OUTFILE"<<endl;
100 }
101
102 int main(int argc, char** argv)
103 try
104 {
105 for (int i = 1; i < argc; i++) {
106 if ((string) argv[i] == "--help") {
107 usage();
108 exit(EXIT_SUCCESS);
109 }
110
111 if ((string) argv[i] == "--version") {
112 cerr<<"dnswasher "<<VERSION<<endl;
113 exit(EXIT_SUCCESS);
114 }
115 }
116
117 if(argc < 3) {
118 usage();
119 exit(1);
120 }
121
122 PcapPacketWriter pw(argv[argc-1]);
123 IPObfuscator ipo;
124 // 0 1 2 3 - argc == 4
125 // dnswasher in1 in2 out
126 for(int n=1; n < argc -1; ++n) {
127 PcapPacketReader pr(argv[n]);
128 pw.setPPR(pr);
129
130 while(pr.getUDPPacket()) {
131 if(ntohs(pr.d_udp->uh_dport)==53 || (ntohs(pr.d_udp->uh_sport)==53 && pr.d_len > sizeof(dnsheader))) {
132 dnsheader* dh=(dnsheader*)pr.d_payload;
133
134 if (pr.d_ip->ip_v == 4){
135 uint32_t *src=(uint32_t*)&pr.d_ip->ip_src;
136 uint32_t *dst=(uint32_t*)&pr.d_ip->ip_dst;
137
138 if(dh->qr)
139 *dst=htonl(ipo.obf4(*dst));
140 else
141 *src=htonl(ipo.obf4(*src));
142
143 pr.d_ip->ip_sum=0;
144 } else if (pr.d_ip->ip_v == 6) {
145 auto src=&pr.d_ip6->ip6_src;
146 auto dst=&pr.d_ip6->ip6_dst;
147
148 if(dh->qr)
149 *dst=ipo.obf6(*dst);
150 else
151 *src=ipo.obf6(*src);
152 }
153 pw.write();
154 }
155 }
156 cerr<<"Saw "<<pr.d_correctpackets<<" correct packets, "<<pr.d_runts<<" runts, "<< pr.d_oversized<<" oversize, "<<
157 pr.d_nonetheripudp<<" unknown encaps"<<endl;
158 }
159 }
160 catch(std::exception& e)
161 {
162 cerr<<"Fatal: "<<e.what()<<endl;
163 }