Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion src/windows/common/VirtioNetworking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,29 @@ static constexpr auto c_eth0DeviceName = L"eth0";
static constexpr auto c_loopbackDeviceName = TEXT(LX_INIT_LOOPBACK_DEVICE_NAME);

VirtioNetworking::VirtioNetworking(
GnsChannel&& gnsChannel, VirtioNetworkingFlags flags, LPCWSTR dnsOptions, std::shared_ptr<GuestDeviceManager> guestDeviceManager, wil::shared_handle userToken) :
GnsChannel&& gnsChannel,
VirtioNetworkingFlags flags,
LPCWSTR dnsOptions,
std::shared_ptr<GuestDeviceManager> guestDeviceManager,
wil::shared_handle userToken,
wil::unique_socket&& dnsHvsocket) :
m_guestDeviceManager(std::move(guestDeviceManager)),
m_userToken(std::move(userToken)),
m_gnsChannel(std::move(gnsChannel)),
m_flags(flags),
m_dnsOptions(dnsOptions)
{
THROW_HR_IF_MSG(
E_INVALIDARG,
((!!dnsHvsocket != WI_IsFlagSet(m_flags, VirtioNetworkingFlags::DnsTunnelingSocket)) ||
(WI_IsFlagSet(m_flags, VirtioNetworkingFlags::DnsTunnelingSocket) && WI_IsFlagSet(m_flags, VirtioNetworkingFlags::DnsTunneling))),
"Incompatible DNS settings");

if (dnsHvsocket)
{
networking::DnsResolverFlags resolverFlags{};
m_dnsTunnelingResolver.emplace(std::move(dnsHvsocket), resolverFlags);
}
}

VirtioNetworking::~VirtioNetworking()
Expand Down Expand Up @@ -196,6 +212,10 @@ try
{
currentDns = networking::HostDnsInfo::GetDnsTunnelingSettings(default_route);
}
else if (WI_IsFlagSet(m_flags, VirtioNetworkingFlags::DnsTunnelingSocket))
{
currentDns = networking::HostDnsInfo::GetDnsTunnelingSettings(TEXT(LX_INIT_DNS_TUNNELING_IP_ADDRESS));
}
else
{
wsl::core::networking::DnsSettingsFlags dnsFlags = networking::DnsSettingsFlags::IncludeVpn;
Expand Down
12 changes: 11 additions & 1 deletion src/windows/common/VirtioNetworking.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "INetworkingEngine.h"
#include "GnsChannel.h"
#include "DnsResolver.h"
#include "WslCoreHostDnsInfo.h"
#include "GnsPortTrackerChannel.h"
#include "GuestDeviceManager.h"
Expand All @@ -16,13 +17,21 @@ enum class VirtioNetworkingFlags
LocalhostRelay = 0x1,
DnsTunneling = 0x2,
Ipv6 = 0x4,
DnsTunnelingSocket = 0x8,
};
DEFINE_ENUM_FLAG_OPERATORS(VirtioNetworkingFlags);

class VirtioNetworking : public INetworkingEngine
{
public:
VirtioNetworking(GnsChannel&& gnsChannel, VirtioNetworkingFlags flags, LPCWSTR dnsOptions, std::shared_ptr<GuestDeviceManager> guestDeviceManager, wil::shared_handle userToken);
VirtioNetworking(
GnsChannel&& gnsChannel,
VirtioNetworkingFlags flags,
LPCWSTR dnsOptions,
std::shared_ptr<GuestDeviceManager> guestDeviceManager,
wil::shared_handle userToken,
wil::unique_socket&& dnsHvsocket = {});

~VirtioNetworking();

// Note: This class cannot be moved because m_networkNotifyHandle captures a 'this' pointer.
Expand Down Expand Up @@ -61,6 +70,7 @@ class VirtioNetworking : public INetworkingEngine
std::shared_ptr<networking::NetworkSettings> m_networkSettings;
VirtioNetworkingFlags m_flags = VirtioNetworkingFlags::None;
LPCWSTR m_dnsOptions = nullptr;
std::optional<networking::DnsResolver> m_dnsTunnelingResolver;
std::optional<GUID> m_localhostAdapterId;
std::optional<GUID> m_adapterId;

Expand Down
29 changes: 10 additions & 19 deletions src/windows/common/WslCoreConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,26 +419,14 @@ void wsl::core::Config::Initialize(_In_opt_ HANDLE UserToken)
{
try
{
// Open a handle to the service control manager and check if the inbox service is registered.
const wil::unique_schandle manager{OpenSCManager(nullptr, nullptr, SC_MANAGER_ENUMERATE_SERVICE)};
THROW_LAST_ERROR_IF(!manager);

// Check if the service is running.
const wil::unique_schandle service{OpenServiceW(manager.get(), L"GlobalSecureAccessTunnelingService", SERVICE_QUERY_STATUS)};
if (service)
if (wsl::windows::common::helpers::IsServiceRunning(L"GlobalSecureAccessTunnelingService"))
{
SERVICE_STATUS status;
THROW_IF_WIN32_BOOL_FALSE(QueryServiceStatus(service.get(), &status));

if (status.dwCurrentState != SERVICE_STOPPED)
if (DnsTunnelingConfigPresence == ConfigKeyPresence::Present)
{
if (DnsTunnelingConfigPresence == ConfigKeyPresence::Present)
{
EMIT_USER_WARNING(wsl::shared::Localization::MessageDnsTunnelingDisabled());
}

EnableDnsTunneling = false;
EMIT_USER_WARNING(wsl::shared::Localization::MessageDnsTunnelingDisabled());
}

EnableDnsTunneling = false;
}
}
CATCH_LOG()
Expand Down Expand Up @@ -474,9 +462,12 @@ void wsl::core::Config::Initialize(_In_opt_ HANDLE UserToken)
EnableVirtio9p = false;
}

if (NetworkingMode != NetworkingMode::Nat && NetworkingMode != NetworkingMode::Mirrored)
if (NetworkingMode != NetworkingMode::Nat && NetworkingMode != NetworkingMode::Mirrored && NetworkingMode != NetworkingMode::VirtioProxy)
{
VALIDATE_CONFIG_OPTION((NetworkingMode != NetworkingMode::Nat && NetworkingMode != NetworkingMode::Mirrored), EnableDnsTunneling, false);
VALIDATE_CONFIG_OPTION(
(NetworkingMode != NetworkingMode::Nat && NetworkingMode != NetworkingMode::Mirrored && NetworkingMode != NetworkingMode::VirtioProxy),
EnableDnsTunneling,
false);
}

if (!EnableDnsTunneling)
Expand Down
23 changes: 23 additions & 0 deletions src/windows/common/helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,29 @@ bool wsl::windows::common::helpers::IsServicePresent(_In_ LPCWSTR ServiceName)
return !!service;
}

bool wsl::windows::common::helpers::IsServiceRunning(_In_ LPCWSTR ServiceName)
{
const wil::unique_schandle manager{OpenSCManager(nullptr, nullptr, SC_MANAGER_CONNECT)};
if (!manager)
{
return false;
}

const wil::unique_schandle service{OpenServiceW(manager.get(), ServiceName, SERVICE_QUERY_STATUS)};
if (!service)
{
return false;
}

SERVICE_STATUS status;
if (!QueryServiceStatus(service.get(), &status))
{
return false;
}

return status.dwCurrentState != SERVICE_STOPPED;
}

bool wsl::windows::common::helpers::IsVirtioSerialConsoleSupported()
{
// See if the Windows version has the required platform change.
Expand Down
2 changes: 2 additions & 0 deletions src/windows/common/helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ bool IsPackageInstalled(_In_ LPCWSTR PackageFamilyName);

bool IsServicePresent(_In_ LPCWSTR ServiceName);

bool IsServiceRunning(_In_ LPCWSTR ServiceName);

bool IsVirtioSerialConsoleSupported();

bool IsVmemmSuffixSupported();
Expand Down
25 changes: 14 additions & 11 deletions src/windows/service/exe/HcsVirtualMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ HcsVirtualMachine::HcsVirtualMachine(_In_ const WSLCSessionSettings* Settings)

THROW_IF_FAILED(CoCreateGuid(&m_vmId));
m_vmIdString = wsl::shared::string::GuidToString<wchar_t>(m_vmId, wsl::shared::string::GuidToStringFlags::Uppercase);
m_featureFlags = static_cast<WSLCFeatureFlags>(Settings->FeatureFlags);
m_featureFlags = Settings->FeatureFlags;
m_networkingMode = Settings->NetworkingMode;
m_bootTimeoutMs = Settings->BootTimeoutMs;

Expand Down Expand Up @@ -369,8 +369,6 @@ try
if (FeatureEnabled(WslcFeatureFlagsDnsTunneling))
{
THROW_HR_IF(E_INVALIDARG, DnsSocket == nullptr);
THROW_HR_IF_MSG(
E_NOTIMPL, m_networkingMode == WSLCNetworkingModeVirtioProxy, "DNS tunneling not supported for VirtioProxy");

THROW_IF_FAILED(wsl::core::networking::DnsResolver::LoadDnsResolverMethods());
dnsSocketHandle.reset(reinterpret_cast<SOCKET>(wslutil::DuplicateHandle(*DnsSocket)));
Expand All @@ -383,34 +381,39 @@ try
if (m_networkingMode == WSLCNetworkingModeNAT)
{
// TODO: refactor this to avoid using wsl config
wsl::core::Config config(nullptr);
if (!wsl::core::NatNetworking::IsHyperVFirewallSupported(config))
m_natConfig.emplace(nullptr);
if (!wsl::core::NatNetworking::IsHyperVFirewallSupported(*m_natConfig))
{
config.FirewallConfig.reset();
m_natConfig->FirewallConfig.reset();
}

// Enable DNS tunneling if a DNS socket was provided
if (FeatureEnabled(WslcFeatureFlagsDnsTunneling))
{
config.EnableDnsTunneling = true;
m_natConfig->EnableDnsTunneling = true;
in_addr address{};
WI_VERIFY(inet_pton(AF_INET, LX_INIT_DNS_TUNNELING_IP_ADDRESS, &address) == 1);
config.DnsTunnelingIpAddress = address.S_un.S_addr;
m_natConfig->DnsTunnelingIpAddress = address.S_un.S_addr;
}

m_networkEngine = std::make_unique<wsl::core::NatNetworking>(
m_computeSystem.get(),
wsl::core::NatNetworking::CreateNetwork(config),
wsl::core::NatNetworking::CreateNetwork(*m_natConfig),
wsl::core::GnsChannel(std::move(gnsSocketHandle)),
config,
*m_natConfig,
std::move(dnsSocketHandle),
nullptr);
}
else if (m_networkingMode == WSLCNetworkingModeVirtioProxy)
{
wsl::core::VirtioNetworkingFlags flags = wsl::core::VirtioNetworkingFlags::Ipv6;
if (FeatureEnabled(WslcFeatureFlagsDnsTunneling))
{
WI_SetFlag(flags, wsl::core::VirtioNetworkingFlags::DnsTunnelingSocket);
}

m_networkEngine = std::make_unique<wsl::core::VirtioNetworking>(
wsl::core::GnsChannel(std::move(gnsSocketHandle)), flags, nullptr, m_guestDeviceManager, m_userToken);
wsl::core::GnsChannel(std::move(gnsSocketHandle)), flags, nullptr, m_guestDeviceManager, m_userToken, std::move(dnsSocketHandle));
}
else
{
Expand Down
2 changes: 2 additions & 0 deletions src/windows/service/exe/HcsVirtualMachine.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Module Name:
#include "GuestDeviceManager.h"
#include "Dmesg.h"
#include "INetworkingEngine.h"
#include "WslCoreConfig.h"
#include <filesystem>
#include <map>

Expand Down Expand Up @@ -79,6 +80,7 @@ class HcsVirtualMachine
wil::unique_socket m_listenSocket;
std::shared_ptr<DmesgCollector> m_dmesgCollector;
std::shared_ptr<GuestDeviceManager> m_guestDeviceManager;
std::optional<wsl::core::Config> m_natConfig;
std::unique_ptr<wsl::core::INetworkingEngine> m_networkEngine;

wil::unique_event m_vmExitEvent{wil::EventOptions::ManualReset};
Expand Down
7 changes: 5 additions & 2 deletions src/windows/service/exe/WslCoreVm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -571,8 +571,9 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken
{
wsl::core::VirtioNetworkingFlags flags = wsl::core::VirtioNetworkingFlags::Ipv6;
WI_SetFlagIf(flags, wsl::core::VirtioNetworkingFlags::LocalhostRelay, m_vmConfig.EnableLocalhostRelay);
WI_SetFlagIf(flags, wsl::core::VirtioNetworkingFlags::DnsTunnelingSocket, m_vmConfig.EnableDnsTunneling);
m_networkingEngine = std::make_unique<wsl::core::VirtioNetworking>(
std::move(gnsChannel), flags, LX_INIT_RESOLVCONF_FULL_HEADER, m_guestDeviceManager, m_userToken);
std::move(gnsChannel), flags, LX_INIT_RESOLVCONF_FULL_HEADER, m_guestDeviceManager, m_userToken, std::move(dnsTunnelingSocket));
}
else if (m_vmConfig.NetworkingMode == NetworkingMode::Bridged)
{
Expand Down Expand Up @@ -1890,7 +1891,9 @@ bool WslCoreVm::InitializeDrvFsLockHeld(_In_ HANDLE UserToken)

bool WslCoreVm::IsDnsTunnelingSupported() const
{
WI_ASSERT(m_vmConfig.NetworkingMode == NetworkingMode::Nat || m_vmConfig.NetworkingMode == NetworkingMode::Mirrored);
WI_ASSERT(
m_vmConfig.NetworkingMode == NetworkingMode::Nat || m_vmConfig.NetworkingMode == NetworkingMode::Mirrored ||
m_vmConfig.NetworkingMode == NetworkingMode::VirtioProxy);

return SUCCEEDED_LOG(wsl::core::networking::DnsResolver::LoadDnsResolverMethods());
}
Expand Down
5 changes: 5 additions & 0 deletions src/windows/wslc/services/SessionModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ SessionOptions::SessionOptions()
{
WI_SetFlag(m_sessionSettings.FeatureFlags, WslcFeatureFlagsVirtioFs);
}

if (settings::User().Get<settings::Setting::SessionDnsTunneling>())
{
WI_SetFlag(m_sessionSettings.FeatureFlags, WslcFeatureFlagsDnsTunneling);
}
}

bool SessionOptions::IsElevated()
Expand Down
5 changes: 5 additions & 0 deletions src/windows/wslc/settings/UserSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ namespace details {
return std::nullopt;
}

WSLC_VALIDATE_SETTING(SessionDnsTunneling)
{
return value;
}

#undef WSLC_VALIDATE_SETTING

} // namespace details
Expand Down
2 changes: 2 additions & 0 deletions src/windows/wslc/settings/UserSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ enum class Setting : size_t
SessionStoragePath,
SessionNetworkingMode,
SessionHostFileShareMode,
SessionDnsTunneling,

Max
};
Expand Down Expand Up @@ -81,6 +82,7 @@ namespace details {
DEFINE_SETTING_MAPPING(SessionStoragePath, std::string, std::wstring, {}, "session.defaultStoragePath")
DEFINE_SETTING_MAPPING(SessionNetworkingMode, std::string, WSLCNetworkingMode, WSLCNetworkingModeVirtioProxy, "session.networkingMode")
DEFINE_SETTING_MAPPING(SessionHostFileShareMode, std::string, HostFileShareMode, HostFileShareMode::VirtioFs, "session.hostFileShareMode")
DEFINE_SETTING_MAPPING(SessionDnsTunneling, bool, bool, false, "session.dnsTunneling")

#undef DEFINE_SETTING_MAPPING
// clang-format on
Expand Down
27 changes: 27 additions & 0 deletions test/windows/NetworkTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5041,5 +5041,32 @@ class VirtioProxyTests
m_config->Update(LxssGenerateTestConfig({.networkingMode = wsl::core::NetworkingMode::VirtioProxy, .dnsTunneling = false}));
NetworkTests::VerifyDnsResolutionRecordTypes();
}

TEST_METHOD(DnsResolutionBasicDnsTunneling)
{
VIRTIOPROXY_TEST_ONLY();
DNS_TUNNELING_TEST_ONLY();

m_config->Update(LxssGenerateTestConfig({.networkingMode = wsl::core::NetworkingMode::VirtioProxy, .dnsTunneling = true}));
NetworkTests::VerifyDnsResolutionBasic();
}

TEST_METHOD(DnsResolutionDigDnsTunneling)
{
VIRTIOPROXY_TEST_ONLY();
DNS_TUNNELING_TEST_ONLY();

m_config->Update(LxssGenerateTestConfig({.networkingMode = wsl::core::NetworkingMode::VirtioProxy, .dnsTunneling = true}));
NetworkTests::VerifyDnsResolutionDig();
}

TEST_METHOD(DnsResolutionRecordTypesDnsTunneling)
{
VIRTIOPROXY_TEST_ONLY();
DNS_TUNNELING_TEST_ONLY();

m_config->Update(LxssGenerateTestConfig({.networkingMode = wsl::core::NetworkingMode::VirtioProxy, .dnsTunneling = true}));
NetworkTests::VerifyDnsResolutionRecordTypes();
}
};
} // namespace NetworkTests
Loading