master
h 439 lines 12.3 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 LxssIptables.h
8
9 Abstract:
10
11 This file contains iptables-related function declarations.
12
13 --*/
14
15 #pragma once
16
17 #include <memory>
18 #include <mutex>
19 #include <mi.h>
20 #include <netfw.h>
21 #include "LxssUserCallback.h"
22
23 /// <summary>
24 /// Type to hold a MI_Session instance. Functions creating an instance of this
25 /// type will construct it in such a way as to also hold an implicit reference
26 /// to the global application instance.
27 /// </summary>
28 using unique_mi_session = std::unique_ptr<MI_Session, std::function<void(MI_Session*)>>;
29
30 /// <summary>
31 /// Type to hold a MI_Instance instance. Functions creating an instance of this
32 /// type will construct it in such a way as to also hold an implicit reference
33 /// to the global application instance.
34 /// </summary>
35 using unique_mi_instance = std::unique_ptr<MI_Instance, std::function<void(MI_Instance*)>>;
36
37 /// <summary>
38 /// Helper class for using Windows Management Interface.
39 /// </summary>
40 class LxssManagementInterface
41 {
42 public:
43 /// <summary>
44 /// Clone an instance.
45 /// </summary>
46 static unique_mi_instance CloneInstance(_In_ const MI_Instance* InstanceToClone);
47
48 /// <summary>
49 /// Closes a MI_Operation instance.
50 /// </summary>
51 static void CloseOperation(MI_Operation* Operation);
52
53 /// <summary>
54 /// Returns the global application instance.
55 /// </summary>
56 static std::shared_ptr<MI_Application> GetGlobalApplication();
57
58 /// <summary>
59 /// Create a new management interface MI_Instance instance.
60 /// </summary>
61 static unique_mi_instance NewInstance(_In_ const std::wstring& ClassName, _In_opt_ const MI_Class* Class);
62
63 /// <summary>
64 /// Create a new management interface session instance.
65 /// </summary>
66 static unique_mi_session NewSession();
67
68 /// <summary>
69 /// Local machine root instance.
70 /// </summary>
71 static const std::wstring& LocalRoot()
72 {
73 return s_localRoot;
74 }
75
76 private:
77 /// <summary>
78 /// Called to destroy the global application instance. Called as a result
79 /// of the last shared reference being deleted.
80 /// </summary>
81 static void CloseGlobalApplication(_Inout_ MI_Application* Application);
82
83 /// <summary>
84 /// Close a MI_Instance. This is implicitly called via the destruction of
85 /// an unique_mi_instance instance.
86 /// </summary>
87 static void CloseInstance(_In_ std::shared_ptr<MI_Application>, _Inout_ MI_Instance* Instance);
88
89 /// <summary>
90 /// Close a session. This is implicitly called via the destruction of an
91 /// unique_mi_session instance.
92 /// </summary>
93 static void CloseSession(_In_ std::shared_ptr<MI_Application>, _Inout_ MI_Session* Session);
94
95 /// <summary>
96 /// Lock for static members.
97 /// </summary>
98 static std::mutex s_lock;
99
100 /// <summary>
101 /// Global MI_Application instance.
102 /// </summary>
103 _Guarded_by_(LxssManagementInterface::s_lock) static std::weak_ptr<MI_Application> s_application;
104
105 /// <summary>
106 /// Local machine root instance.
107 /// </summary>
108 static const std::wstring s_localRoot;
109 };
110
111 /// <summary>
112 /// MI_Operation unique instance.
113 /// </summary>
114 using unique_mi_operation =
115 wil::unique_struct<MI_Operation, decltype(LxssManagementInterface::CloseOperation), LxssManagementInterface::CloseOperation>;
116
117 class LxssNetworkingFirewallPort;
118 class LxssNetworkingNat;
119
120 /// <summary>
121 /// Emulate iptables functionality.
122 /// </summary>
123 class LxssIpTables
124 {
125 public:
126 /// <summary>
127 /// Constructor.
128 /// </summary>
129 LxssIpTables();
130
131 /// <summary>
132 /// Enable iptables emulation.
133 /// </summary>
134 void EnableIpTablesSupport(_In_ const wil::unique_handle& InstanceHandle);
135
136 /// <summary>
137 /// Cleanup any persistent data leftover from a non-clean shutdown.
138 /// </summary>
139 static void CleanupRemnants();
140
141 /// <summary>
142 /// Helper routine to convert an IP address into the string equivalent.
143 /// </summary>
144 static std::wstring AddressStringFromAddress(const IP_ADDRESS_PREFIX& Address, bool AddPrefixLength);
145
146 private:
147 /// <summary>
148 /// No copy constructor.
149 /// </summary>
150 LxssIpTables(const LxssIpTables&) = delete;
151
152 /// <summary>
153 /// Verify the input prefix address is supported.
154 /// </summary>
155 static bool IsAllowedInputPrefix(_In_ CONST IP_ADDRESS_PREFIX& InputPrefix);
156
157 /// <summary>
158 /// Kernel-mode callback function for iptables operations.
159 /// </summary>
160 NTSTATUS
161 KernelCallback(_In_ PVOID CallbackBuffer, _In_ ULONG_PTR CallbackBufferSize);
162
163 /// <summary>
164 /// Kernel-mode callback function to configure a port rule via the Windows
165 /// firewall.
166 /// </summary>
167 NTSTATUS
168 KernelCallbackFirewallPort(_In_ PLXBUS_USER_CALLBACK_IPTABLES_DATA CallbackData);
169
170 /// <summary>
171 /// Kernel-mode callback function to add a new masquerade entry.
172 /// </summary>
173 NTSTATUS
174 KernelCallbackMasquerade(_In_ PLXBUS_USER_CALLBACK_IPTABLES_DATA CallbackData);
175
176 /// <summary>
177 /// Kernel-mode callback entrypoint function for iptables operations.
178 /// </summary>
179 static NTSTATUS KernelCallbackProxy(_Inout_ LxssIpTables* Self, _In_ PVOID CallbackBuffer, _In_ ULONG_PTR CallbackBufferSize);
180
181 /// <summary>
182 /// List of port rules.
183 /// </summary>
184 std::list<std::unique_ptr<LxssNetworkingFirewallPort>> m_firewallPorts;
185
186 /// <summary>
187 /// Lock to protect class members.
188 /// </summary>
189 std::mutex m_lock;
190
191 /// <summary>
192 /// List of NATs.
193 /// </summary>
194 std::list<std::unique_ptr<LxssNetworkingNat>> m_networkTranslators;
195
196 /// <summary>
197 /// Callback for the kernel-mode driver to make iptables requests.
198 /// </summary>
199 // N.B. This is the last member of the class because it needs to be
200 // destructed early as the asynchronous callback may rely on other
201 // members of the class being valid.
202 std::unique_ptr<LxssUserCallback> m_kernelCallback;
203 };
204
205 /// <summary>
206 /// Class providing access to Windows firewall
207 /// </summary>
208 class LxssNetworkingFirewall
209 {
210 public:
211 /// <summary>
212 /// Default constructor.
213 /// </summary>
214 LxssNetworkingFirewall();
215
216 /// <summary>
217 /// Create a rule to allow the specified address and port combination.
218 /// </summary>
219 std::wstring AddPortRule(const IP_ADDRESS_PREFIX& Address) const;
220
221 /// <summary>
222 /// Cleanup any persistent data leftover from a non-clean shutdown.
223 /// </summary>
224 static void CleanupRemnants();
225
226 /// <summary>
227 /// Exclude a network adapter from the firewall's public profile.
228 /// </summary>
229 void ExcludeAdapter(const std::wstring& AdapterName);
230
231 /// <summary>
232 /// Remove a network adapter from the exclusion list.
233 /// </summary>
234 void RemoveExcludedAdapter(const std::wstring& AdapterName);
235
236 /// <summary>
237 /// Remove a port rule created by AddPortRule.
238 /// </summary>
239 void RemovePortRule(const std::wstring& RuleName) const;
240
241 private:
242 /// <summary>
243 /// No copy constructor.
244 /// </summary>
245 LxssNetworkingFirewall(const LxssNetworkingFirewall&) = delete;
246
247 /// <summary>
248 /// Copies part of a source array to a destination array.
249 /// </summary>
250 static void CopyPartialArray(SAFEARRAY* Destination, SAFEARRAY* Source, ULONG DestinationIndexStart, ULONG SourceIndexStart, ULONG ElementsToCopy);
251
252 /// <summary>
253 /// Creates the unique friendly name of the firewall port rule.
254 /// </summary>
255 static std::wstring GeneratePortRuleName(const IP_ADDRESS_PREFIX& Address);
256
257 /// <summary>
258 /// Returns the existing array of excluded adapters.
259 /// </summary>
260 wil::unique_variant GetExcludedAdapters(_Out_opt_ ULONG* AdapterCount) const;
261
262 /// <summary>
263 /// COM firewall instance.
264 /// </summary>
265 wil::com_ptr<INetFwPolicy2> m_firewall;
266
267 /// <summary>
268 /// Lock to protect class members.
269 /// </summary>
270 std::mutex m_lock;
271
272 /// <summary>
273 /// Firewall rule description.
274 /// </summary>
275 static const wil::unique_bstr s_DefaultRuleDescription;
276
277 /// <summary>
278 /// Prefix to uniquely identify WSL firewall rules.
279 /// </summary>
280 static const std::wstring s_FriendlyNamePrefix;
281 };
282
283 /// <summary>
284 /// Class representing a Windows firewall port open rule, removed on
285 /// destruction.
286 /// </summary>
287 class LxssNetworkingFirewallPort
288 {
289 public:
290 /// <summary>
291 /// Constructor.
292 /// </summary>
293 LxssNetworkingFirewallPort(const std::shared_ptr<LxssNetworkingFirewall>& Firewall, const IP_ADDRESS_PREFIX& Address);
294
295 /// <summary>
296 /// Constructor to take ownership of an existing rule.
297 /// </summary>
298 LxssNetworkingFirewallPort(const std::shared_ptr<LxssNetworkingFirewall>& Firewall, const wil::com_ptr<INetFwRule>& Existing);
299
300 /// <summary>
301 /// Destructor.
302 /// </summary>
303 ~LxssNetworkingFirewallPort();
304
305 /// <summary>
306 /// Returns the address and port of the firewall rule.
307 /// </summary>
308 const IP_ADDRESS_PREFIX& Address() const
309 {
310 return m_address;
311 }
312
313 /// <summary>
314 /// Returns the underlying firewall instance.
315 /// </summary>
316 const std::shared_ptr<LxssNetworkingFirewall> Firewall() const
317 {
318 return m_firewall;
319 }
320
321 private:
322 /// <summary>
323 /// No default constructor.
324 /// </summary>
325 LxssNetworkingFirewallPort() = delete;
326 /// <summary>
327 /// No copy constructor.
328 /// </summary>
329 LxssNetworkingFirewallPort(const LxssNetworkingFirewallPort&) = delete;
330
331 /// <summary>
332 /// Address information for the port rule.
333 /// </summary>
334 IP_ADDRESS_PREFIX m_address;
335
336 /// <summary>
337 /// Pointer to the firewall interface.
338 /// </summary>
339 std::shared_ptr<LxssNetworkingFirewall> m_firewall;
340
341 /// <summary>
342 /// The unique rule name.
343 /// </summary>
344 std::wstring m_name;
345 };
346
347 /// <summary>
348 /// Class representing a Windows NAT instance.
349 /// </summary>
350 class LxssNetworkingNat
351 {
352 public:
353 /// <summary>
354 /// Constructor.
355 /// </summary>
356 LxssNetworkingNat(const IP_ADDRESS_PREFIX& InputPrefix);
357
358 /// <summary>
359 /// Constructor to take ownership of an existing NAT.
360 /// N.B. Not setting m_internalIpAddress as the only usage of this
361 /// constructor is to wrap an existing instance for cleanup/deletion.
362 /// If this constructor is to be used for other purposes, need to
363 /// fetch the s_WmiNatInternalIpAddress property and convert it.
364 /// </summary>
365 LxssNetworkingNat(const MI_Instance* ExistingInstance);
366
367 /// <summary>
368 /// Destructor.
369 /// </summary>
370 ~LxssNetworkingNat();
371
372 /// <summary>
373 /// The address being NAT'd.
374 /// </summary>
375 const IP_ADDRESS_PREFIX& Address() const
376 {
377 return m_internalIpAddress;
378 }
379
380 /// <summary>
381 /// Cleanup any persistent data leftover from a non-clean shutdown.
382 /// </summary>
383 static void CleanupRemnants();
384
385 private:
386 /// <summary>
387 /// No default constructor.
388 /// </summary>
389 LxssNetworkingNat() = delete;
390 /// <summary>
391 /// No copy constructor.
392 /// </summary>
393 LxssNetworkingNat(const LxssNetworkingNat&) = delete;
394
395 /// <summary>
396 /// The NAT instance.
397 /// </summary>
398 unique_mi_instance m_natInstance;
399
400 /// <summary>
401 /// The session used to create/destroy the NAT.
402 /// </summary>
403 unique_mi_session m_session;
404
405 /// <summary>
406 /// Create a new WMI instance of the NAT type.
407 /// </summary>
408 static unique_mi_instance GetNatWmiInstance(const unique_mi_session& Session);
409
410 /// <summary>
411 /// The IP address prefix to NAT.
412 /// </summary>
413 IP_ADDRESS_PREFIX m_internalIpAddress;
414
415 /// <summary>
416 /// The string prefix for the friendly NAT name.
417 /// </summary>
418 static const std::wstring s_FriendlyNamePrefix;
419
420 /// <summary>
421 /// The string representing the NAT instance ID in WMI.
422 /// </summary>
423 static const std::wstring s_WmiNatInstanceId;
424
425 /// <summary>
426 /// The string representing the NAT internal IP address prefix in WMI.
427 /// </summary>
428 static const std::wstring s_WmiNatInternalIpAddress;
429
430 /// <summary>
431 /// The string representing the NAT name property in WMI.
432 /// </summary>
433 static const std::wstring s_WmiNatName;
434
435 /// <summary>
436 /// The string representing the NAT namespace in WMI.
437 /// </summary>
438 static const std::wstring s_WmiNatNamespace;
439 };