blob: 973c9aaedaa22e084673e71e3c664d5c7f7ba335 [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 Evans77e9a132021-05-13 10:51:13 +090023#include "dns-proxy/chrome_features_service_client.h"
Garrick Evans34650b32021-02-03 09:24:35 +090024#include "dns-proxy/resolver.h"
Garrick Evans77e9a132021-05-13 10:51:13 +090025#include "dns-proxy/session_monitor.h"
Garrick Evans34650b32021-02-03 09:24:35 +090026
Garrick Evans066dc2c2020-12-10 10:43:55 +090027namespace dns_proxy {
28
29// The process that runs the actual proxying code.
30class Proxy : public brillo::DBusDaemon {
31 public:
32 enum class Type { kSystem, kDefault, kARC };
33
34 struct Options {
35 Type type;
36 // Required for ARC proxies as it specifies which physical interface
37 // should (always) be tracked. This field is ignored (but should be empty)
38 // for the system and default network proxies.
39 std::string ifname;
40 };
41
42 explicit Proxy(const Options& opts);
Garrick Evans5fe2a4f2021-02-03 17:04:48 +090043 // For testing.
44 Proxy(const Options& opts,
45 std::unique_ptr<patchpanel::Client> patchpanel,
46 std::unique_ptr<shill::Client> shill);
Garrick Evans066dc2c2020-12-10 10:43:55 +090047 Proxy(const Proxy&) = delete;
48 Proxy& operator=(const Proxy&) = delete;
Garrick Evans9c8797d2021-02-17 21:28:10 +090049 ~Proxy();
Garrick Evans066dc2c2020-12-10 10:43:55 +090050
51 static const char* TypeToString(Type t);
52 static std::optional<Type> StringToType(const std::string& s);
53
54 protected:
55 int OnInit() override;
56 void OnShutdown(int*) override;
57
Garrick Evans2ca050d2021-02-09 18:21:36 +090058 // Added for testing.
Jason Jeremy Iman845f2932021-01-31 16:12:13 +090059 virtual std::unique_ptr<Resolver> NewResolver(base::TimeDelta timeout,
60 base::TimeDelta retry_delay,
61 int max_num_retries);
Garrick Evans2ca050d2021-02-09 18:21:36 +090062
Garrick Evans066dc2c2020-12-10 10:43:55 +090063 private:
Garrick Evans9c7afb82021-01-29 22:38:03 +090064 static const uint8_t kMaxShillPropertyRetries = 10;
65
Garrick Evansd41fdbf2021-03-03 09:15:48 +090066 // Helper for parsing and applying shill's DNSProxyDOHProviders property.
67 class DoHConfig {
68 public:
69 DoHConfig() = default;
70 DoHConfig(const DoHConfig&) = delete;
71 DoHConfig& operator=(const DoHConfig&) = delete;
72 ~DoHConfig() = default;
73
74 // Stores the resolver to configure whenever settings are updated.
75 void set_resolver(Resolver* resolver);
76
77 // |nameservers| is the list of name servers for the network the proxy is
78 // tracking.
79 void set_nameservers(const std::vector<std::string>& nameservers);
80
81 // |settings| is the DoH providers property we get from shill. It keys, as
82 // applicable, secure DNS provider endpoints to standard DNS name servers.
Garrick Evans9e5cd1e2021-03-11 22:07:44 +090083 void set_providers(const brillo::VariantDictionary& providers);
Garrick Evansd41fdbf2021-03-03 09:15:48 +090084
85 void clear();
86
87 private:
88 void update();
89
90 Resolver* resolver_{nullptr};
91 std::vector<std::string> nameservers_;
92 // If non-empty, the secure providers to use for always-on DoH.
93 std::set<std::string> secure_providers_;
94 // If non-empty, maps name servers to secure DNS providers, for automatic
95 // update.
96 std::map<std::string, std::string> auto_providers_;
97 };
98
Garrick Evans066dc2c2020-12-10 10:43:55 +090099 void Setup();
100 void OnPatchpanelReady(bool success);
Garrick Evans4f5428c2021-02-15 11:23:54 +0900101 void OnPatchpanelReset(bool reset);
Garrick Evansfe99aaa2021-02-12 14:32:50 +0900102 void OnShillReady(bool success);
Garrick Evans9c7afb82021-01-29 22:38:03 +0900103 void OnShillReset(bool reset);
Garrick Evans066dc2c2020-12-10 10:43:55 +0900104
Garrick Evans77e9a132021-05-13 10:51:13 +0900105 // Triggered by the session monitor whenever the user logs in or out.
106 void OnSessionStateChanged(bool login);
107
108 // Triggered by the Chrome features client in response to checking the status
109 // of the DNSProxyEnabled feature value.
110 void OnFeatureEnabled(base::Optional<bool> enabled);
111 void Enable();
112 void Disable();
113
Garrick Evans34650b32021-02-03 09:24:35 +0900114 // Triggered whenever the device attached to the default network changes.
115 // |device| can be null and indicates the default service is disconnected.
116 void OnDefaultDeviceChanged(const shill::Client::Device* const device);
117 void OnDeviceChanged(const shill::Client::Device* const device);
Garrick Evans066dc2c2020-12-10 10:43:55 +0900118
Garrick Evans73e8e5e2021-04-27 10:16:26 +0900119 void MaybeCreateResolver();
Garrick Evansa8c12be2021-02-17 16:06:45 +0900120 void UpdateNameServers(const shill::Client::IPConfig& ipconfig);
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900121 void OnDoHProvidersChanged(const brillo::Any& value);
Garrick Evansa8c12be2021-02-17 16:06:45 +0900122
Garrick Evans48c84ef2021-01-28 11:29:42 +0900123 // Helper func for setting the dns-proxy address in shill.
124 // Only valid for the system proxy.
Garrick Evans9c7afb82021-01-29 22:38:03 +0900125 // Will retry on failure up to |num_retries| before possibly crashing the
126 // proxy.
127 void SetShillProperty(const std::string& addr,
128 bool die_on_failure = false,
129 uint8_t num_retries = kMaxShillPropertyRetries);
Garrick Evans48c84ef2021-01-28 11:29:42 +0900130
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900131 // Return the property accessor, creating it if needed.
132 shill::Client::ManagerPropertyAccessor* shill_props();
133
Garrick Evans5fe2a4f2021-02-03 17:04:48 +0900134 FRIEND_TEST(ProxyTest, SystemProxy_OnShutdownClearsAddressPropertyOnShill);
135 FRIEND_TEST(ProxyTest, NonSystemProxy_OnShutdownDoesNotCallShill);
136 FRIEND_TEST(ProxyTest, SystemProxy_SetShillPropertyWithNoRetriesCrashes);
137 FRIEND_TEST(ProxyTest, SystemProxy_SetShillPropertyDoesntCrashIfDieFalse);
Garrick Evansab03c462021-02-15 20:54:20 +0900138 FRIEND_TEST(ProxyTest, ShillInitializedWhenReady);
Garrick Evans5fe2a4f2021-02-03 17:04:48 +0900139 FRIEND_TEST(ProxyTest, SystemProxy_ConnectedNamedspace);
140 FRIEND_TEST(ProxyTest, DefaultProxy_ConnectedNamedspace);
141 FRIEND_TEST(ProxyTest, ArcProxy_ConnectedNamedspace);
142 FRIEND_TEST(ProxyTest, CrashOnConnectNamespaceFailure);
143 FRIEND_TEST(ProxyTest, CrashOnPatchpanelNotReady);
144 FRIEND_TEST(ProxyTest, ShillResetRestoresAddressProperty);
Garrick Evans2ca050d2021-02-09 18:21:36 +0900145 FRIEND_TEST(ProxyTest, StateClearedIfDefaultServiceDrops);
146 FRIEND_TEST(ProxyTest, ArcProxy_IgnoredIfDefaultServiceDrops);
147 FRIEND_TEST(ProxyTest, StateClearedIfDefaultServiceIsNotOnline);
148 FRIEND_TEST(ProxyTest, NewResolverStartsListeningOnDefaultServiceComesOnline);
149 FRIEND_TEST(ProxyTest, CrashOnListenFailure);
150 FRIEND_TEST(ProxyTest, NameServersUpdatedOnDefaultServiceComesOnline);
151 FRIEND_TEST(ProxyTest,
152 SystemProxy_ShillPropertyUpdatedOnDefaultServiceComesOnline);
Garrick Evansadde9852021-02-15 20:16:53 +0900153 FRIEND_TEST(ProxyTest, SystemProxy_IgnoresVPN);
154 FRIEND_TEST(ProxyTest, SystemProxy_GetsPhysicalDeviceOnInitialVPN);
155 FRIEND_TEST(ProxyTest, DefaultProxy_UsesVPN);
Garrick Evans73e8e5e2021-04-27 10:16:26 +0900156 FRIEND_TEST(ProxyTest, ArcProxy_NameServersUpdatedOnDeviceChangeEvent);
157 FRIEND_TEST(ProxyTest, SystemProxy_NameServersUpdatedOnDeviceChangeEvent);
Garrick Evansa8c12be2021-02-17 16:06:45 +0900158 FRIEND_TEST(ProxyTest, DeviceChangeEventIgnored);
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900159 FRIEND_TEST(ProxyTest, BasicDoHDisable);
160 FRIEND_TEST(ProxyTest, BasicDoHAlwaysOn);
161 FRIEND_TEST(ProxyTest, BasicDoHAutomatic);
Garrick Evans4e1fc312021-05-10 14:47:31 +0900162 FRIEND_TEST(ProxyTest, RemovesDNSQueryParameterTemplate_AlwaysOn);
163 FRIEND_TEST(ProxyTest, RemovesDNSQueryParameterTemplate_Automatic);
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900164 FRIEND_TEST(ProxyTest, NewResolverConfiguredWhenSet);
165 FRIEND_TEST(ProxyTest, DoHModeChangingFixedNameServers);
166 FRIEND_TEST(ProxyTest, MultipleDoHProvidersForAlwaysOnMode);
167 FRIEND_TEST(ProxyTest, MultipleDoHProvidersForAutomaticMode);
168 FRIEND_TEST(ProxyTest, DoHBadAlwaysOnConfigSetsAutomaticMode);
Garrick Evans77e9a132021-05-13 10:51:13 +0900169 FRIEND_TEST(ProxyTest, FeatureEnablementCheckedOnSetup);
170 FRIEND_TEST(ProxyTest, LoginEventTriggersFeatureCheck);
171 FRIEND_TEST(ProxyTest, LogoutEventTriggersDisable);
172 FRIEND_TEST(ProxyTest, FeatureEnabled_LoginAfterLogout);
173 FRIEND_TEST(ProxyTest, FeatureDisabled_LoginAfterLogout);
174 FRIEND_TEST(ProxyTest, SystemProxy_ShillPropertyNotUpdatedIfFeatureDisabled);
Garrick Evans5fe2a4f2021-02-03 17:04:48 +0900175
Garrick Evans066dc2c2020-12-10 10:43:55 +0900176 const Options opts_;
177 std::unique_ptr<patchpanel::Client> patchpanel_;
178 std::unique_ptr<shill::Client> shill_;
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900179 std::unique_ptr<shill::Client::ManagerPropertyAccessor> shill_props_;
Garrick Evans77e9a132021-05-13 10:51:13 +0900180 std::unique_ptr<ChromeFeaturesServiceClient> features_;
181 std::unique_ptr<SessionMonitor> session_;
Garrick Evans066dc2c2020-12-10 10:43:55 +0900182
183 base::ScopedFD ns_fd_;
Garrick Evans9c7afb82021-01-29 22:38:03 +0900184 patchpanel::ConnectNamespaceResponse ns_;
Garrick Evans34650b32021-02-03 09:24:35 +0900185 std::unique_ptr<Resolver> resolver_;
Garrick Evansd41fdbf2021-03-03 09:15:48 +0900186 DoHConfig doh_config_;
Garrick Evans34650b32021-02-03 09:24:35 +0900187 std::unique_ptr<shill::Client::Device> device_;
Garrick Evans066dc2c2020-12-10 10:43:55 +0900188
Garrick Evans77e9a132021-05-13 10:51:13 +0900189 bool feature_enabled_{false};
Garrick Evans066dc2c2020-12-10 10:43:55 +0900190 base::WeakPtrFactory<Proxy> weak_factory_{this};
191};
192
193std::ostream& operator<<(std::ostream& stream, Proxy::Type type);
194std::ostream& operator<<(std::ostream& stream, Proxy::Options opt);
195
196} // namespace dns_proxy
197
198#endif // DNS_PROXY_PROXY_H_