1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/dns/public/doh_provider_entry.h"
6
7 #include <utility>
8
9 #include "base/check_op.h"
10 #include "base/feature_list.h"
11 #include "base/no_destructor.h"
12 #include "base/ranges/algorithm.h"
13 #include "net/dns/public/dns_over_https_server_config.h"
14 #include "net/dns/public/util.h"
15
16 namespace net {
17
18 namespace {
19
ParseIPs(const std::set<base::StringPiece> & ip_strs)20 std::set<IPAddress> ParseIPs(const std::set<base::StringPiece>& ip_strs) {
21 std::set<IPAddress> ip_addresses;
22 for (base::StringPiece ip_str : ip_strs) {
23 IPAddress ip_address;
24 bool success = ip_address.AssignFromIPLiteral(ip_str);
25 DCHECK(success);
26 ip_addresses.insert(std::move(ip_address));
27 }
28 return ip_addresses;
29 }
30
ParseValidDohTemplate(std::string server_template)31 DnsOverHttpsServerConfig ParseValidDohTemplate(std::string server_template) {
32 auto parsed_template =
33 DnsOverHttpsServerConfig::FromString(std::move(server_template));
34 DCHECK(parsed_template.has_value()); // Template must be valid.
35 return std::move(*parsed_template);
36 }
37
38 } // namespace
39
40 #define MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(feature_name, feature_state) \
41 ([]() { \
42 static BASE_FEATURE(k##feature_name, #feature_name, feature_state); \
43 return &k##feature_name; \
44 })()
45
46 // static
GetList()47 const DohProviderEntry::List& DohProviderEntry::GetList() {
48 // See /net/docs/adding_doh_providers.md for instructions on modifying this
49 // DoH provider list.
50 //
51 // The provider names in these entries should be kept in sync with the
52 // DohProviderId histogram suffix list in
53 // tools/metrics/histograms/metadata/histogram_suffixes_list.xml.
54 static const base::NoDestructor<DohProviderEntry::List> providers{{
55 new DohProviderEntry(
56 "AlekBergNl",
57 MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
58 DohProviderAlekBergNl, base::FEATURE_ENABLED_BY_DEFAULT),
59 DohProviderIdForHistogram::kAlekBergNl,
60 /*ip_strs=*/{}, /*dns_over_tls_hostnames=*/{},
61 "https://dnsnl.alekberg.net/dns-query{?dns}",
62 /*ui_name=*/"alekberg.net (NL)",
63 /*privacy_policy=*/"https://alekberg.net/privacy",
64 /*display_globally=*/false,
65 /*display_countries=*/{"NL"}, LoggingLevel::kNormal),
66 new DohProviderEntry(
67 "CleanBrowsingAdult",
68 MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
69 DohProviderCleanBrowsingAdult, base::FEATURE_ENABLED_BY_DEFAULT),
70 /*provider_id_for_histogram=*/absl::nullopt,
71 {"185.228.168.10", "185.228.169.11", "2a0d:2a00:1::1",
72 "2a0d:2a00:2::1"},
73 /*dns_over_tls_hostnames=*/{"adult-filter-dns.cleanbrowsing.org"},
74 "https://doh.cleanbrowsing.org/doh/adult-filter{?dns}",
75 /*ui_name=*/"", /*privacy_policy=*/"",
76 /*display_globally=*/false, /*display_countries=*/{},
77 LoggingLevel::kNormal),
78 new DohProviderEntry(
79 "CleanBrowsingFamily",
80 MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
81 DohProviderCleanBrowsingFamily, base::FEATURE_ENABLED_BY_DEFAULT),
82 DohProviderIdForHistogram::kCleanBrowsingFamily,
83 {"185.228.168.168", "185.228.169.168",
84 "2a0d:2a00:1::", "2a0d:2a00:2::"},
85 /*dns_over_tls_hostnames=*/{"family-filter-dns.cleanbrowsing.org"},
86 "https://doh.cleanbrowsing.org/doh/family-filter{?dns}",
87 /*ui_name=*/"CleanBrowsing (Family Filter)",
88 /*privacy_policy=*/"https://cleanbrowsing.org/privacy",
89 /*display_globally=*/true, /*display_countries=*/{},
90 LoggingLevel::kNormal),
91 new DohProviderEntry(
92 "CleanBrowsingSecure",
93 MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
94 DohProviderCleanBrowsingSecure, base::FEATURE_ENABLED_BY_DEFAULT),
95 /*provider_id_for_histogram=*/absl::nullopt,
96 {"185.228.168.9", "185.228.169.9", "2a0d:2a00:1::2",
97 "2a0d:2a00:2::2"},
98 /*dns_over_tls_hostnames=*/{"security-filter-dns.cleanbrowsing.org"},
99 "https://doh.cleanbrowsing.org/doh/security-filter{?dns}",
100 /*ui_name=*/"", /*privacy_policy=*/"", /*display_globally=*/false,
101 /*display_countries=*/{}, LoggingLevel::kNormal),
102 new DohProviderEntry(
103 "Cloudflare",
104 MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
105 DohProviderCloudflare, base::FEATURE_ENABLED_BY_DEFAULT),
106 DohProviderIdForHistogram::kCloudflare,
107 {"1.1.1.1", "1.0.0.1", "2606:4700:4700::1111",
108 "2606:4700:4700::1001"},
109 /*dns_over_tls_hostnames=*/
110 {"one.one.one.one", "1dot1dot1dot1.cloudflare-dns.com"},
111 "https://chrome.cloudflare-dns.com/dns-query",
112 /*ui_name=*/"Cloudflare (1.1.1.1)",
113 "https://developers.cloudflare.com/1.1.1.1/privacy/"
114 /*privacy_policy=*/"public-dns-resolver/",
115 /*display_globally=*/true, /*display_countries=*/{},
116 LoggingLevel::kExtra),
117 new DohProviderEntry(
118 "Comcast",
119 MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
120 DohProviderComcast, base::FEATURE_ENABLED_BY_DEFAULT),
121 /*provider_id_for_histogram=*/absl::nullopt,
122 {"75.75.75.75", "75.75.76.76", "2001:558:feed::1",
123 "2001:558:feed::2"},
124 /*dns_over_tls_hostnames=*/{"dot.xfinity.com"},
125 "https://doh.xfinity.com/dns-query{?dns}", /*ui_name=*/"",
126 /*privacy_policy*/ "", /*display_globally=*/false,
127 /*display_countries=*/{}, LoggingLevel::kExtra),
128 new DohProviderEntry(
129 "Cox",
130 MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
131 DohProviderCox, base::FEATURE_DISABLED_BY_DEFAULT),
132 /*provider_id_for_histogram=*/absl::nullopt,
133 {"68.105.28.11", "68.105.28.12", "2001:578:3f::30"},
134 /*dns_over_tls_hostnames=*/{"dot.cox.net"},
135 "https://doh.cox.net/dns-query",
136 /*ui_name=*/"", /*privacy_policy=*/"",
137 /*display_globally=*/false, /*display_countries=*/{},
138 LoggingLevel::kNormal),
139 new DohProviderEntry(
140 "Cznic",
141 MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
142 DohProviderCznic, base::FEATURE_ENABLED_BY_DEFAULT),
143 DohProviderIdForHistogram::kCznic,
144 {"185.43.135.1", "193.17.47.1", "2001:148f:fffe::1",
145 "2001:148f:ffff::1"},
146 /*dns_over_tls_hostnames=*/{"odvr.nic.cz"}, "https://odvr.nic.cz/doh",
147 /*ui_name=*/"CZ.NIC ODVR",
148 /*privacy_policy=*/"https://www.nic.cz/odvr/",
149 /*display_globally=*/false, /*display_countries=*/{"CZ"},
150 LoggingLevel::kNormal),
151 new DohProviderEntry(
152 "Dnssb",
153 MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
154 DohProviderDnssb, base::FEATURE_ENABLED_BY_DEFAULT),
155 DohProviderIdForHistogram::kDnsSb,
156 {"185.222.222.222", "45.11.45.11", "2a09::", "2a11::"},
157 /*dns_over_tls_hostnames=*/{"dns.sb"},
158 "https://doh.dns.sb/dns-query{?dns}", /*ui_name=*/"DNS.SB",
159 /*privacy_policy=*/"https://dns.sb/privacy/",
160 /*display_globally=*/false, /*display_countries=*/{"EE", "DE"},
161 LoggingLevel::kNormal),
162 new DohProviderEntry(
163 "Google",
164 MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
165 DohProviderGoogle, base::FEATURE_ENABLED_BY_DEFAULT),
166 DohProviderIdForHistogram::kGoogle,
167 {"8.8.8.8", "8.8.4.4", "2001:4860:4860::8888",
168 "2001:4860:4860::8844"},
169 /*dns_over_tls_hostnames=*/
170 {"dns.google", "dns.google.com", "8888.google"},
171 "https://dns.google/dns-query{?dns}",
172 /*ui_name=*/"Google (Public DNS)",
173 "https://developers.google.com/speed/public-dns/"
174 /*privacy_policy=*/"privacy",
175 /*display_globally=*/true, /*display_countries=*/{},
176 LoggingLevel::kExtra),
177 new DohProviderEntry(
178 "GoogleDns64",
179 MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
180 DohProviderGoogleDns64, base::FEATURE_ENABLED_BY_DEFAULT),
181 /*provider_id_for_histogram=*/absl::nullopt,
182 {"2001:4860:4860::64", "2001:4860:4860::6464"},
183 /*dns_over_tls_hostnames=*/{"dns64.dns.google"},
184 "https://dns64.dns.google/dns-query{?dns}",
185 /*ui_name=*/"", /*privacy_policy=*/"",
186 /*display_globally=*/false,
187 /*display_countries=*/{}, LoggingLevel::kNormal),
188 new DohProviderEntry(
189 "Iij",
190 MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
191 DohProviderIij, base::FEATURE_ENABLED_BY_DEFAULT),
192 DohProviderIdForHistogram::kIij, /*ip_strs=*/{},
193 /*dns_over_tls_hostnames=*/{}, "https://public.dns.iij.jp/dns-query",
194 /*ui_name=*/"IIJ (Public DNS)",
195 /*privacy_policy=*/"https://public.dns.iij.jp/",
196 /*display_globally=*/false, /*display_countries=*/{"JP"},
197 LoggingLevel::kNormal),
198 new DohProviderEntry(
199 "NextDns",
200 MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
201 DohProviderNextDns, base::FEATURE_ENABLED_BY_DEFAULT),
202 DohProviderIdForHistogram::kNextDns, /*ip_strs=*/{},
203 /*dns_over_tls_hostnames=*/{}, "https://chromium.dns.nextdns.io",
204 /*ui_name=*/"NextDNS",
205 /*privacy_policy=*/"https://nextdns.io/privacy",
206 /*display_globally=*/false, /*display_countries=*/{"US"},
207 LoggingLevel::kNormal),
208 new DohProviderEntry(
209 "OpenDNS",
210 MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
211 DohProviderOpenDNS, base::FEATURE_ENABLED_BY_DEFAULT),
212 DohProviderIdForHistogram::kOpenDns,
213 {"208.67.222.222", "208.67.220.220", "2620:119:35::35",
214 "2620:119:53::53"},
215 /*dns_over_tls_hostnames=*/{},
216 "https://doh.opendns.com/dns-query{?dns}", /*ui_name=*/"OpenDNS",
217 "https://www.cisco.com/c/en/us/about/legal/"
218 /*privacy_policy=*/"privacy-full.html",
219 /*display_globally=*/true, /*display_countries=*/{},
220 LoggingLevel::kNormal),
221 new DohProviderEntry(
222 "OpenDNSFamily",
223 MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
224 DohProviderOpenDNSFamily, base::FEATURE_ENABLED_BY_DEFAULT),
225 /*provider_id_for_histogram=*/absl::nullopt,
226 {"208.67.222.123", "208.67.220.123", "2620:119:35::123",
227 "2620:119:53::123"},
228 /*dns_over_tls_hostnames=*/{},
229 "https://doh.familyshield.opendns.com/dns-query{?dns}",
230 /*ui_name=*/"", /*privacy_policy=*/"", /*display_globally=*/false,
231 /*display_countries=*/{}, LoggingLevel::kNormal),
232 new DohProviderEntry(
233 "Quad9Cdn",
234 MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
235 DohProviderQuad9Cdn, base::FEATURE_ENABLED_BY_DEFAULT),
236 /*provider_id_for_histogram=*/absl::nullopt,
237 {"9.9.9.11", "149.112.112.11", "2620:fe::11", "2620:fe::fe:11"},
238 /*dns_over_tls_hostnames=*/{"dns11.quad9.net"},
239 "https://dns11.quad9.net/dns-query", /*ui_name=*/"",
240 /*privacy_policy=*/"", /*display_globally=*/false,
241 /*display_countries=*/{}, LoggingLevel::kNormal),
242 new DohProviderEntry(
243 "Quad9Insecure",
244 MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
245 DohProviderQuad9Insecure, base::FEATURE_ENABLED_BY_DEFAULT),
246 /*provider_id_for_histogram=*/absl::nullopt,
247 {"9.9.9.10", "149.112.112.10", "2620:fe::10", "2620:fe::fe:10"},
248 /*dns_over_tls_hostnames=*/{"dns10.quad9.net"},
249 "https://dns10.quad9.net/dns-query", /*ui_name=*/"",
250 /*privacy_policy=*/"", /*display_globally=*/false,
251 /*display_countries=*/{}, LoggingLevel::kNormal),
252 new DohProviderEntry(
253 "Quad9Secure",
254 MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
255 DohProviderQuad9Secure, base::FEATURE_DISABLED_BY_DEFAULT),
256 DohProviderIdForHistogram::kQuad9Secure,
257 {"9.9.9.9", "149.112.112.112", "2620:fe::fe", "2620:fe::9"},
258 /*dns_over_tls_hostnames=*/{"dns.quad9.net", "dns9.quad9.net"},
259 "https://dns.quad9.net/dns-query", /*ui_name=*/"Quad9 (9.9.9.9)",
260 /*privacy_policy=*/"https://www.quad9.net/home/privacy/",
261 /*display_globally=*/true, /*display_countries=*/{},
262 LoggingLevel::kExtra),
263 new DohProviderEntry(
264 "Quickline",
265 MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
266 DohProviderQuickline, base::FEATURE_ENABLED_BY_DEFAULT),
267 /*provider_id_for_histogram=*/absl::nullopt,
268 {"212.60.61.246", "212.60.63.246", "2001:1a88:10:ffff::1",
269 "2001:1a88:10:ffff::2"},
270 /*dns_over_tls_hostnames=*/{"dot.quickline.ch"},
271 "https://doh.quickline.ch/dns-query{?dns}",
272 /*ui_name=*/"", /*privacy_policy=*/"",
273 /*display_globally=*/false,
274 /*display_countries=*/{}, LoggingLevel::kNormal),
275 new DohProviderEntry(
276 "Spectrum1",
277 MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
278 DohProviderSpectrum1, base::FEATURE_ENABLED_BY_DEFAULT),
279 /*provider_id_for_histogram=*/absl::nullopt,
280 {"209.18.47.61", "209.18.47.62", "2001:1998:0f00:0001::1",
281 "2001:1998:0f00:0002::1"},
282 /*dns_over_tls_hostnames=*/{},
283 "https://doh-01.spectrum.com/dns-query{?dns}",
284 /*ui_name=*/"", /*privacy_policy=*/"",
285 /*display_globally=*/false,
286 /*display_countries=*/{}, LoggingLevel::kNormal),
287 new DohProviderEntry(
288 "Spectrum2",
289 MAKE_BASE_FEATURE_WITH_STATIC_STORAGE(
290 DohProviderSpectrum2, base::FEATURE_ENABLED_BY_DEFAULT),
291 /*provider_id_for_histogram=*/absl::nullopt,
292 {"209.18.47.61", "209.18.47.62", "2001:1998:0f00:0001::1",
293 "2001:1998:0f00:0002::1"},
294 /*dns_over_tls_hostnames=*/{},
295 "https://doh-02.spectrum.com/dns-query{?dns}",
296 /*ui_name=*/"", /*privacy_policy=*/"",
297 /*display_globally=*/false,
298 /*display_countries=*/{}, LoggingLevel::kNormal),
299 }};
300 return *providers;
301 }
302
303 #undef MAKE_BASE_FEATURE_WITH_STATIC_STORAGE
304
305 // static
ConstructForTesting(std::string provider,const base::Feature * feature,absl::optional<DohProviderIdForHistogram> provider_id_for_histogram,std::set<base::StringPiece> ip_strs,std::set<std::string> dns_over_tls_hostnames,std::string dns_over_https_template,std::string ui_name,std::string privacy_policy,bool display_globally,std::set<std::string> display_countries,LoggingLevel logging_level)306 DohProviderEntry DohProviderEntry::ConstructForTesting(
307 std::string provider,
308 const base::Feature* feature,
309 absl::optional<DohProviderIdForHistogram> provider_id_for_histogram,
310 std::set<base::StringPiece> ip_strs,
311 std::set<std::string> dns_over_tls_hostnames,
312 std::string dns_over_https_template,
313 std::string ui_name,
314 std::string privacy_policy,
315 bool display_globally,
316 std::set<std::string> display_countries,
317 LoggingLevel logging_level) {
318 return DohProviderEntry(provider, feature, provider_id_for_histogram, ip_strs,
319 dns_over_tls_hostnames, dns_over_https_template,
320 ui_name, privacy_policy, display_globally,
321 display_countries, logging_level);
322 }
323
324 DohProviderEntry::~DohProviderEntry() = default;
325
DohProviderEntry(std::string provider,const base::Feature * feature,absl::optional<DohProviderIdForHistogram> provider_id_for_histogram,std::set<base::StringPiece> ip_strs,std::set<std::string> dns_over_tls_hostnames,std::string dns_over_https_template,std::string ui_name,std::string privacy_policy,bool display_globally,std::set<std::string> display_countries,LoggingLevel logging_level)326 DohProviderEntry::DohProviderEntry(
327 std::string provider,
328 const base::Feature* feature,
329 absl::optional<DohProviderIdForHistogram> provider_id_for_histogram,
330 std::set<base::StringPiece> ip_strs,
331 std::set<std::string> dns_over_tls_hostnames,
332 std::string dns_over_https_template,
333 std::string ui_name,
334 std::string privacy_policy,
335 bool display_globally,
336 std::set<std::string> display_countries,
337 LoggingLevel logging_level)
338 : provider(std::move(provider)),
339 feature(*feature),
340 provider_id_for_histogram(std::move(provider_id_for_histogram)),
341 ip_addresses(ParseIPs(ip_strs)),
342 dns_over_tls_hostnames(std::move(dns_over_tls_hostnames)),
343 doh_server_config(
344 ParseValidDohTemplate(std::move(dns_over_https_template))),
345 ui_name(std::move(ui_name)),
346 privacy_policy(std::move(privacy_policy)),
347 display_globally(display_globally),
348 display_countries(std::move(display_countries)),
349 logging_level(logging_level) {
350 DCHECK(!display_globally || this->display_countries.empty());
351 if (display_globally || !this->display_countries.empty()) {
352 DCHECK(!this->ui_name.empty());
353 DCHECK(!this->privacy_policy.empty());
354 DCHECK(this->provider_id_for_histogram.has_value());
355 }
356 for (const auto& display_country : this->display_countries) {
357 DCHECK_EQ(2u, display_country.size());
358 }
359 }
360
361 } // namespace net
362