De-inline vpn/win32.hpp

pull/1969/head
Jason Rhinelander 2 years ago
parent 2a27698016
commit bb85ec4595
No known key found for this signature in database
GPG Key ID: C4992CE7A88D4262

@ -58,6 +58,7 @@ endif()
if (WIN32)
target_sources(lokinet-platform PRIVATE
net/win32.cpp
vpn/win32.cpp
win32/exec.cpp)
add_library(lokinet-win32 STATIC
win32/dll.cpp

@ -0,0 +1,159 @@
#include "vpn/win32.hpp"
namespace llarp::win32
{
namespace
{
template <typename T>
std::string
ip_to_string(T ip)
{
return var::visit([](auto&& ip) { return ip.ToString(); }, ip);
}
} // namespace
void
VPNPlatform::Route(std::string ip, std::string gw, std::string cmd)
{
llarp::win32::Exec(
"route.exe", fmt::format("{} {} MASK 255.255.255.255 {} METRIC {}", cmd, ip, gw, m_Metric));
}
void
VPNPlatform::DefaultRouteViaInterface(NetworkInterface& vpn, std::string cmd)
{
// route hole for loopback bacause god is dead on windows
llarp::win32::Exec(
"route.exe", fmt::format("{} 127.0.0.0 MASK 255.0.0.0 0.0.0.0 METRIC {}", cmd, m_Metric));
// set up ipv4 routes
auto lower = RouteViaInterface(vpn, "0.0.0.0", "128.0.0.0", cmd);
auto upper = RouteViaInterface(vpn, "128.0.0.0", "128.0.0.0", cmd);
}
OneShotExec
VPNPlatform::RouteViaInterface(
NetworkInterface& vpn, std::string addr, std::string mask, std::string cmd)
{
const auto& info = vpn.Info();
auto index = info.index;
if (index == 0)
{
if (auto maybe_idx = net::Platform::Default_ptr()->GetInterfaceIndex(info[0]))
index = *maybe_idx;
}
auto ifaddr = ip_to_string(info[0]);
// this changes the last 1 to a 0 so that it routes over the interface
// this is required because windows is idiotic af
ifaddr.back()--;
if (index)
{
return OneShotExec{
"route.exe",
fmt::format(
"{} {} MASK {} {} IF {} METRIC {}", cmd, addr, mask, ifaddr, info.index, m_Metric)};
}
else
{
return OneShotExec{
"route.exe",
fmt::format("{} {} MASK {} {} METRIC {}", cmd, addr, mask, ifaddr, m_Metric)};
}
}
void
VPNPlatform::AddRoute(net::ipaddr_t ip, net::ipaddr_t gateway)
{
Route(ip_to_string(ip), ip_to_string(gateway), "ADD");
}
void
VPNPlatform::DelRoute(net::ipaddr_t ip, net::ipaddr_t gateway)
{
Route(ip_to_string(ip), ip_to_string(gateway), "DELETE");
}
void
VPNPlatform::AddRouteViaInterface(NetworkInterface& vpn, IPRange range)
{
RouteViaInterface(vpn, range.BaseAddressString(), range.NetmaskString(), "ADD");
}
void
VPNPlatform::DelRouteViaInterface(NetworkInterface& vpn, IPRange range)
{
RouteViaInterface(vpn, range.BaseAddressString(), range.NetmaskString(), "DELETE");
}
std::vector<net::ipaddr_t>
VPNPlatform::GetGatewaysNotOnInterface(NetworkInterface& vpn)
{
std::vector<net::ipaddr_t> gateways;
auto idx = vpn.Info().index;
using UInt_t = decltype(idx);
for (const auto& iface : Net().AllNetworkInterfaces())
{
if (static_cast<UInt_t>(iface.index) == idx)
continue;
if (iface.gateway)
gateways.emplace_back(*iface.gateway);
}
return gateways;
}
void
VPNPlatform::AddDefaultRouteViaInterface(NetworkInterface& vpn)
{
// kill ipv6
llarp::win32::Exec(
"WindowsPowerShell\\v1.0\\powershell.exe",
"-Command (Disable-NetAdapterBinding -Name \"* \" -ComponentID ms_tcpip6)");
DefaultRouteViaInterface(vpn, "ADD");
llarp::win32::Exec("ipconfig.exe", "/flushdns");
}
void
VPNPlatform::DelDefaultRouteViaInterface(NetworkInterface& vpn)
{
// restore ipv6
llarp::win32::Exec(
"WindowsPowerShell\\v1.0\\powershell.exe",
"-Command (Enable-NetAdapterBinding -Name \"* \" -ComponentID ms_tcpip6)");
DefaultRouteViaInterface(vpn, "DELETE");
llarp::win32::Exec("netsh.exe", "winsock reset");
llarp::win32::Exec("ipconfig.exe", "/flushdns");
}
std::shared_ptr<NetworkInterface>
VPNPlatform::ObtainInterface(InterfaceInfo info, AbstractRouter* router)
{
return wintun::make_interface(std::move(info), router);
}
std::shared_ptr<I_Packet_IO>
VPNPlatform::create_packet_io(unsigned int ifindex)
{
// we only want do this on all interfaes with windivert
if (ifindex)
throw std::invalid_argument{
"cannot create packet io on explicitly specified interface, not currently supported on "
"windows (yet)"};
std::string filter{"outbound and ( udp.DstPort == 53 or tcp.DstPort == 53 )"};
if (auto dscp = _ctx->router->GetConfig()->dns.m_queryDSCP.value_or(0))
{
// DSCP is the first 6 bits of the TOS field (the last 2 are ECN).
auto tos = dscp << 2;
fmt::format_to(std::back_inserter(filter), " and ip.TOS != {}", tos);
}
return WinDivert::make_interceptor(filter, [router = _ctx->router] { router->TriggerPump(); });
}
};
} // namespace llarp::win32

@ -16,16 +16,6 @@
namespace llarp::win32
{
namespace
{
template <typename T>
std::string
ip_to_string(T ip)
{
return var::visit([](auto&& ip) { return ip.ToString(); }, ip);
}
} // namespace
using namespace llarp::vpn;
class VPNPlatform : public Platform, public IRouteManager
{
@ -39,53 +29,13 @@ namespace llarp::win32
}
void
Route(std::string ip, std::string gw, std::string cmd)
{
llarp::win32::Exec(
"route.exe",
fmt::format("{} {} MASK 255.255.255.255 {} METRIC {}", cmd, ip, gw, m_Metric));
}
Route(std::string ip, std::string gw, std::string cmd);
void
DefaultRouteViaInterface(NetworkInterface& vpn, std::string cmd)
{
// route hole for loopback bacause god is dead on windows
llarp::win32::Exec(
"route.exe", fmt::format("{} 127.0.0.0 MASK 255.0.0.0 0.0.0.0 METRIC {}", cmd, m_Metric));
// set up ipv4 routes
auto lower = RouteViaInterface(vpn, "0.0.0.0", "128.0.0.0", cmd);
auto upper = RouteViaInterface(vpn, "128.0.0.0", "128.0.0.0", cmd);
}
DefaultRouteViaInterface(NetworkInterface& vpn, std::string cmd);
OneShotExec
RouteViaInterface(NetworkInterface& vpn, std::string addr, std::string mask, std::string cmd)
{
const auto& info = vpn.Info();
auto index = info.index;
if (index == 0)
{
if (auto maybe_idx = net::Platform::Default_ptr()->GetInterfaceIndex(info[0]))
index = *maybe_idx;
}
auto ifaddr = ip_to_string(info[0]);
// this changes the last 1 to a 0 so that it routes over the interface
// this is required because windows is idiotic af
ifaddr.back()--;
if (index)
{
return OneShotExec{
"route.exe",
fmt::format(
"{} {} MASK {} {} IF {} METRIC {}", cmd, addr, mask, ifaddr, info.index, m_Metric)};
}
else
{
return OneShotExec{
"route.exe",
fmt::format("{} {} MASK {} {} METRIC {}", cmd, addr, mask, ifaddr, m_Metric)};
}
}
RouteViaInterface(NetworkInterface& vpn, std::string addr, std::string mask, std::string cmd);
public:
VPNPlatform(const VPNPlatform&) = delete;
@ -94,92 +44,34 @@ namespace llarp::win32
VPNPlatform(llarp::Context* ctx) : Platform{}, _ctx{ctx}
{}
virtual ~VPNPlatform() = default;
~VPNPlatform() override = default;
void
AddRoute(net::ipaddr_t ip, net::ipaddr_t gateway) override
{
Route(ip_to_string(ip), ip_to_string(gateway), "ADD");
}
AddRoute(net::ipaddr_t ip, net::ipaddr_t gateway) override;
void
DelRoute(net::ipaddr_t ip, net::ipaddr_t gateway) override
{
Route(ip_to_string(ip), ip_to_string(gateway), "DELETE");
}
DelRoute(net::ipaddr_t ip, net::ipaddr_t gateway) override;
void
AddRouteViaInterface(NetworkInterface& vpn, IPRange range) override
{
RouteViaInterface(vpn, range.BaseAddressString(), range.NetmaskString(), "ADD");
}
AddRouteViaInterface(NetworkInterface& vpn, IPRange range) override;
void
DelRouteViaInterface(NetworkInterface& vpn, IPRange range) override
{
RouteViaInterface(vpn, range.BaseAddressString(), range.NetmaskString(), "DELETE");
}
DelRouteViaInterface(NetworkInterface& vpn, IPRange range) override;
std::vector<net::ipaddr_t>
GetGatewaysNotOnInterface(NetworkInterface& vpn) override
{
std::vector<net::ipaddr_t> gateways;
auto idx = vpn.Info().index;
using UInt_t = decltype(idx);
for (const auto& iface : Net().AllNetworkInterfaces())
{
if (static_cast<UInt_t>(iface.index) == idx)
continue;
if (iface.gateway)
gateways.emplace_back(*iface.gateway);
}
return gateways;
}
GetGatewaysNotOnInterface(NetworkInterface& vpn) override;
void
AddDefaultRouteViaInterface(NetworkInterface& vpn) override
{
// kill ipv6
llarp::win32::Exec(
"WindowsPowerShell\\v1.0\\powershell.exe",
"-Command (Disable-NetAdapterBinding -Name \"* \" -ComponentID ms_tcpip6)");
DefaultRouteViaInterface(vpn, "ADD");
llarp::win32::Exec("ipconfig.exe", "/flushdns");
}
AddDefaultRouteViaInterface(NetworkInterface& vpn) override;
void
DelDefaultRouteViaInterface(NetworkInterface& vpn) override
{
// restore ipv6
llarp::win32::Exec(
"WindowsPowerShell\\v1.0\\powershell.exe",
"-Command (Enable-NetAdapterBinding -Name \"* \" -ComponentID ms_tcpip6)");
DefaultRouteViaInterface(vpn, "DELETE");
llarp::win32::Exec("netsh.exe", "winsock reset");
llarp::win32::Exec("ipconfig.exe", "/flushdns");
}
DelDefaultRouteViaInterface(NetworkInterface& vpn) override;
std::shared_ptr<NetworkInterface>
ObtainInterface(InterfaceInfo info, AbstractRouter* router) override
{
return wintun::make_interface(std::move(info), router);
}
ObtainInterface(InterfaceInfo info, AbstractRouter* router) override;
std::shared_ptr<I_Packet_IO>
create_packet_io(unsigned int ifindex) override
{
// we only want do this on all interfaes with windivert
if (ifindex)
throw std::invalid_argument{
"cannot create packet io on explicitly specified interface, not currently supported on "
"windows (yet)"};
return WinDivert::make_interceptor(
"outbound and ( udp.DstPort == 53 or tcp.DstPort == 53 )",
[router = _ctx->router] { router->TriggerPump(); });
}
create_packet_io(unsigned int ifindex) override;
IRouteManager&
RouteManager() override

Loading…
Cancel
Save