blob: 3ea63dab1243babbf1aba6c5a2903e654c45344f [file] [log] [blame]
Garrick Evans066dc2c2020-12-10 10:43:55 +09001// Copyright 2021 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef DNS_PROXY_PROXY_H_
6#define DNS_PROXY_PROXY_H_
7
8#include <iostream>
Garrick Evansd41fdbf2021-03-03 09:15:48 +09009#include <map>
Garrick Evans066dc2c2020-12-10 10:43:55 +090010#include <memory>
11#include <optional>
Garrick Evansd41fdbf2021-03-03 09:15:48 +090012#include <set>
Garrick Evans066dc2c2020-12-10 10:43:55 +090013#include <string>
Garrick Evansd41fdbf2021-03-03 09:15:48 +090014#include <vector>
Garrick Evans066dc2c2020-12-10 10:43:55 +090015
16#include <base/memory/weak_ptr.h>
17#include <base/files/scoped_file.h>
18#include <brillo/daemons/dbus_daemon.h>
19#include <chromeos/patchpanel/dbus/client.h>
Garrick Evans5fe2a4f2021-02-03 17:04:48 +090020#include <gtest/gtest_prod.h> // for FRIEND_TEST
Garrick Evans066dc2c2020-12-10 10:43:55 +090021#include <shill/dbus/client/client.h>
22
Garrick Evans34650b32021-02-03 09:24:35 +090023#include "dns-proxy/resolver.h"
24
Garrick Evans066dc2c2020-12-10 10:43:55 +090025namespace dns_proxy {
26
27// The process that runs the actual proxying code.
28class Proxy : public brillo::DBusDaemon {
29 public:
30 enum class Type { kSystem, kDefault, kARC };
31
32 struct Options {
33 Type type;
34 // Required for ARC proxies as it specifies which physical interface
35 // should (always) be tracked. This field is ignored (but should be empty)
36 // for the system and default network proxies.
37 std::string ifname;
38 };
39
40 explicit Proxy(const Options& opts);
Garrick Evans5fe2a4f2021-02-03 17:04:48 +090041 // For testing.
42 Proxy(const Options& opts,
43 std::unique_ptr<patchpanel::Client> patchpanel,
44 std::unique_ptr<shill::Client> shill);
Garrick Evans066dc2c2020-12-10 10:43:55 +090045 Proxy(const Proxy&) = delete;
46 Proxy& operator=(const Proxy&) = delete;
Garrick Evans9c8797d2021-02-17 21:28:10 +090047 ~Proxy();
Garrick Evans066dc2c2020-12-10 10:43:55 +090048
49 static const char* TypeToString(Type t);
50 static std::optional<Type> StringToType(const std::string& s);
51
52 protected:
53 int OnInit() override;
54 void OnShutdown(int*) override;
55
Garrick Evans2ca050d2021-02-09 18:21:36 +090056 // Added for testing.
Jason Jeremy Iman845f2932021-01-31 16:12:13 +090057 virtual std::unique_ptr<Resolver> NewResolver(base::TimeDelta timeout,
58 base::TimeDelta retry_delay,
59 int max_num_retries);
Garrick Evans2ca050d2021-02-09 18:21:36 +090060
Garrick Evans066dc2c2020-12-10 10:43:55 +090061 private:
Garrick Evans9c7afb82021-01-29 22:38:03 +090062 static const uint8_t kMaxShillPropertyRetries = 10;
63
Garrick Evansd41fdbf2021-03-03 09:15:48 +090064 // Helper for parsing and applying shill's DNSProxyDOHProviders property.
65 class DoHConfig {
66 public:
67 DoHConfig() = default;
68 DoHConfig(const DoHConfig&) = delete;
69 DoHConfig& operator=(const DoHConfig&) = delete;
70 ~DoHConfig() = default;
71
72 // Stores the resolver to configure whenever settings are updated.
73 void set_resolver(Resolver* resolver);
74
75 // |nameservers| is the list of name servers for the network the proxy is
76 // tracking.
77 void set_nameservers(const std::vector<std::string>& nameservers);
78
79 // |settings| is the DoH providers property we get from shill. It keys, as
80 // applicable, secure DNS provider endpoints to standard DNS name servers.
Garrick Evans9e5cd1e2021-03-11 22:07:44 +090081 void set_providers(const brillo::VariantDictionary& providers);
Garrick Evansd41fdbf2021-03-03 09:15:48 +090082
83 void clear();
84
85 private:
86 void update();
87
88 Resolver* resolver_{nullptr};
89 std::vector<std::string> nameservers_;
90 // If non-empty, the secure providers to use for always-on DoH.
91 std::set<std::string> secure_providers_;
92 // If non-empty, maps name servers to secure DNS providers, for automatic
93 // update.
94 std::map<std::string, std::string> auto_providers_;
95 };
96
Garrick Evans066dc2c2020-12-10 10:43:55 +090097 void Setup();
98 void OnPatchpanelReady(bool success);
Garrick Evans4f5428c2021-02-15 11:23:54 +090099 void OnPatchpanelReset(bool reset);
Garrick Evansfe99aaa2021-02-12 14:32:50 +0900100 void OnShillReady(bool success);
Garrick Evans9c7afb82021-01-29 22:38:03 +0900101 void OnShillReset(bool reset);
Garrick Evans066dc2c2020-12-10 10:43:55 +0900102
Garrick Evans34650b32021-02-03 09:24:35 +0900103 // Triggered whenever the device attached to the default network changes.
104 // |device| can be null and indicates the default service is disconnected.
105 void OnDefaultDeviceChanged(const shill::Client::Device* const device);
106 void OnDeviceChanged(const shill::Client::Device* const device);
Garrick Evans066dc2c2020-12-10 10:43:55 +0900107
Garrick Evans73e8e5e2021-04-27 10:16:26 +0900108 void MaybeCreateResolver();
Garrick Evansa8c12be2021-02-17 16:06:45 +0900109 void UpdateNameServers(const shill::Client::IPConfig& ipconfig);
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900110 void OnDoHProvidersChanged(const brillo::Any& value);
Garrick Evansa8c12be2021-02-17 16:06:45 +0900111
Garrick Evans48c84ef2021-01-28 11:29:42 +0900112 // Helper func for setting the dns-proxy address in shill.
113 // Only valid for the system proxy.
Garrick Evans9c7afb82021-01-29 22:38:03 +0900114 // Will retry on failure up to |num_retries| before possibly crashing the
115 // proxy.
116 void SetShillProperty(const std::string& addr,
117 bool die_on_failure = false,
118 uint8_t num_retries = kMaxShillPropertyRetries);
Garrick Evans48c84ef2021-01-28 11:29:42 +0900119
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900120 // Return the property accessor, creating it if needed.
121 shill::Client::ManagerPropertyAccessor* shill_props();
122
Garrick Evans5fe2a4f2021-02-03 17:04:48 +0900123 FRIEND_TEST(ProxyTest, SystemProxy_OnShutdownClearsAddressPropertyOnShill);
124 FRIEND_TEST(ProxyTest, NonSystemProxy_OnShutdownDoesNotCallShill);
125 FRIEND_TEST(ProxyTest, SystemProxy_SetShillPropertyWithNoRetriesCrashes);
126 FRIEND_TEST(ProxyTest, SystemProxy_SetShillPropertyDoesntCrashIfDieFalse);
Garrick Evansab03c462021-02-15 20:54:20 +0900127 FRIEND_TEST(ProxyTest, ShillInitializedWhenReady);
Garrick Evans5fe2a4f2021-02-03 17:04:48 +0900128 FRIEND_TEST(ProxyTest, SystemProxy_ConnectedNamedspace);
129 FRIEND_TEST(ProxyTest, DefaultProxy_ConnectedNamedspace);
130 FRIEND_TEST(ProxyTest, ArcProxy_ConnectedNamedspace);
131 FRIEND_TEST(ProxyTest, CrashOnConnectNamespaceFailure);
132 FRIEND_TEST(ProxyTest, CrashOnPatchpanelNotReady);
133 FRIEND_TEST(ProxyTest, ShillResetRestoresAddressProperty);
Garrick Evans2ca050d2021-02-09 18:21:36 +0900134 FRIEND_TEST(ProxyTest, StateClearedIfDefaultServiceDrops);
135 FRIEND_TEST(ProxyTest, ArcProxy_IgnoredIfDefaultServiceDrops);
136 FRIEND_TEST(ProxyTest, StateClearedIfDefaultServiceIsNotOnline);
137 FRIEND_TEST(ProxyTest, NewResolverStartsListeningOnDefaultServiceComesOnline);
138 FRIEND_TEST(ProxyTest, CrashOnListenFailure);
139 FRIEND_TEST(ProxyTest, NameServersUpdatedOnDefaultServiceComesOnline);
140 FRIEND_TEST(ProxyTest,
141 SystemProxy_ShillPropertyUpdatedOnDefaultServiceComesOnline);
Garrick Evansadde9852021-02-15 20:16:53 +0900142 FRIEND_TEST(ProxyTest, SystemProxy_IgnoresVPN);
143 FRIEND_TEST(ProxyTest, SystemProxy_GetsPhysicalDeviceOnInitialVPN);
144 FRIEND_TEST(ProxyTest, DefaultProxy_UsesVPN);
Garrick Evans73e8e5e2021-04-27 10:16:26 +0900145 FRIEND_TEST(ProxyTest, ArcProxy_NameServersUpdatedOnDeviceChangeEvent);
146 FRIEND_TEST(ProxyTest, SystemProxy_NameServersUpdatedOnDeviceChangeEvent);
Garrick Evansa8c12be2021-02-17 16:06:45 +0900147 FRIEND_TEST(ProxyTest, DeviceChangeEventIgnored);
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900148 FRIEND_TEST(ProxyTest, BasicDoHDisable);
149 FRIEND_TEST(ProxyTest, BasicDoHAlwaysOn);
150 FRIEND_TEST(ProxyTest, BasicDoHAutomatic);
Garrick Evans4e1fc312021-05-10 14:47:31 +0900151 FRIEND_TEST(ProxyTest, RemovesDNSQueryParameterTemplate_AlwaysOn);
152 FRIEND_TEST(ProxyTest, RemovesDNSQueryParameterTemplate_Automatic);
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900153 FRIEND_TEST(ProxyTest, NewResolverConfiguredWhenSet);
154 FRIEND_TEST(ProxyTest, DoHModeChangingFixedNameServers);
155 FRIEND_TEST(ProxyTest, MultipleDoHProvidersForAlwaysOnMode);
156 FRIEND_TEST(ProxyTest, MultipleDoHProvidersForAutomaticMode);
157 FRIEND_TEST(ProxyTest, DoHBadAlwaysOnConfigSetsAutomaticMode);
Garrick Evans5fe2a4f2021-02-03 17:04:48 +0900158
Garrick Evans066dc2c2020-12-10 10:43:55 +0900159 const Options opts_;
160 std::unique_ptr<patchpanel::Client> patchpanel_;
161 std::unique_ptr<shill::Client> shill_;
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900162 std::unique_ptr<shill::Client::ManagerPropertyAccessor> shill_props_;
Garrick Evans066dc2c2020-12-10 10:43:55 +0900163
164 base::ScopedFD ns_fd_;
Garrick Evans9c7afb82021-01-29 22:38:03 +0900165 patchpanel::ConnectNamespaceResponse ns_;
Garrick Evans34650b32021-02-03 09:24:35 +0900166 std::unique_ptr<Resolver> resolver_;
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900167 DoHConfig doh_config_;
Garrick Evans34650b32021-02-03 09:24:35 +0900168 std::unique_ptr<shill::Client::Device> device_;
Garrick Evans066dc2c2020-12-10 10:43:55 +0900169
170 base::WeakPtrFactory<Proxy> weak_factory_{this};
171};
172
173std::ostream& operator<<(std::ostream& stream, Proxy::Type type);
174std::ostream& operator<<(std::ostream& stream, Proxy::Options opt);
175
176} // namespace dns_proxy
177
178#endif // DNS_PROXY_PROXY_H_