master
cpp 98 lines 4.41 KB
Raw
1 // Copyright (C) Microsoft Corporation. All rights reserved.
2
3 #include "precomp.h"
4 #include "WslCoreTcpIpStateTracking.h"
5
6 #include "WslCoreConfig.h"
7 #include "WslCoreFirewallSupport.h"
8
9 // SyncFirewallState is only needed when running on a Windows build with the original Hyper-V Firewall API (shipped with Windows
10 // 11 22H2) later updates to the Hyper-V Firewall solve the below automatically
11 void wsl::core::networking::IpStateTracking::SyncFirewallState(const NetworkSettings& preferredNetwork) noexcept
12 try
13 {
14 // This function is used to update rules which are IP address based. These
15 // rules are updated whenever we detect IP address changes.
16 // If we have tracked IP addresses, we add or update the rules.
17 // If we no longer have any tracked IP addresses, we remove the rules.
18 // Currently, we add the following rules:
19 // -My IP loopback rule - allows traffic from my IP addresses
20 // -Local subnet rule - allows traffic from the local subnet
21
22 if (FirewallVmCreatorId.has_value())
23 {
24 // Obtain current set of IP addresses
25 std::set<EndpointIpAddress> currentIpAddresses;
26 if (!preferredNetwork.PreferredIpAddress.AddressString.empty())
27 {
28 currentIpAddresses.insert(preferredNetwork.PreferredIpAddress);
29 }
30 for (const auto& ipAddress : preferredNetwork.IpAddresses)
31 {
32 currentIpAddresses.insert(ipAddress);
33 }
34
35 // Only perform firewall update if the IP addresses have changed
36 if (currentIpAddresses != FirewallTrackedIpAddresses)
37 {
38 // Ensure COM state is properly initialized
39 const auto coInit = InitializeCOMState();
40 const auto loopbackRuleId = MakeLoopbackFirewallRuleId(FirewallVmCreatorId.value());
41 const auto localSubnetRuleId = MakeLocalSubnetFirewallRuleId(FirewallVmCreatorId.value());
42
43 // If we have no IP addresses, remove any existing rules
44 if (currentIpAddresses.empty())
45 {
46 WSL_LOG("IpStateTracking::SyncFirewallState removing rules");
47
48 // Remove loopback rule
49 RemoveHyperVFirewallRule(loopbackRuleId);
50
51 // Remove local subnet rule
52 RemoveHyperVFirewallRule(localSubnetRuleId);
53 }
54 else
55 {
56 // We have IP addresses - update the firewall rules
57 FirewallRuleConfiguration myIpLoopbackRule{MakeLoopbackFirewallRuleConfiguration(loopbackRuleId)};
58 FirewallRuleConfiguration localSubnetRule{MakeLocalSubnetFirewallRuleConfiguration(localSubnetRuleId)};
59
60 // Iterate through IP Addresses to populate myIP loopback addresses and local subnet addresses
61 std::set<std::wstring> localSubnetPrefixes;
62 for (const auto& ipAddress : currentIpAddresses)
63 {
64 myIpLoopbackRule.RemoteAddresses.emplace_back(wil::make_bstr(ipAddress.AddressString.c_str()));
65 localSubnetPrefixes.insert(ipAddress.GetPrefix());
66 }
67
68 // Convert from set of wstring to vector of unique_bstr
69 for (const auto& subnet : localSubnetPrefixes)
70 {
71 localSubnetRule.RemoteAddresses.emplace_back(wil::make_bstr(subnet.c_str()));
72 }
73
74 // Add my IP loopback rule
75 WSL_LOG("IpStateTracking::SyncFirewallState Adding my IP loopback rule");
76 AddHyperVFirewallRule(FirewallVmCreatorId.value(), myIpLoopbackRule);
77
78 // Add local subnet rule
79 WSL_LOG("IpStateTracking::SyncFirewallState Adding local subnet rule");
80 AddHyperVFirewallRule(FirewallVmCreatorId.value(), localSubnetRule);
81 }
82
83 // Swap to the tracked set of IP addresses after we have performed all of the updates
84 std::swap(FirewallTrackedIpAddresses, currentIpAddresses);
85 }
86 else
87 {
88 WSL_LOG(
89 "IpStateTracking::SyncFirewallState - FirewallTrackedIpAddresses is synced with the preferredNetwork",
90 TraceLoggingValue(FirewallTrackedIpAddresses.size(), "FirewallTrackedIpAddresses.size"));
91 }
92 }
93 else
94 {
95 WSL_LOG("IpStateTracking::SyncFirewallState - no FirewallVmCreatorId");
96 }
97 }
98 CATCH_LOG()