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