From bb85ec459575adbdc83022f2143103833d8c7dd7 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Tue, 13 Sep 2022 13:25:27 -0300 Subject: [PATCH] De-inline vpn/win32.hpp --- llarp/CMakeLists.txt | 1 + llarp/vpn/win32.cpp | 159 +++++++++++++++++++++++++++++++++++++++++++ llarp/vpn/win32.hpp | 134 ++++-------------------------------- 3 files changed, 173 insertions(+), 121 deletions(-) create mode 100644 llarp/vpn/win32.cpp diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index b860822d7..b794f6ead 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -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 diff --git a/llarp/vpn/win32.cpp b/llarp/vpn/win32.cpp new file mode 100644 index 000000000..d8401f36e --- /dev/null +++ b/llarp/vpn/win32.cpp @@ -0,0 +1,159 @@ +#include "vpn/win32.hpp" + +namespace llarp::win32 +{ + + namespace + { + template + 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 + VPNPlatform::GetGatewaysNotOnInterface(NetworkInterface& vpn) + { + std::vector gateways; + + auto idx = vpn.Info().index; + using UInt_t = decltype(idx); + for (const auto& iface : Net().AllNetworkInterfaces()) + { + if (static_cast(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 + VPNPlatform::ObtainInterface(InterfaceInfo info, AbstractRouter* router) + { + return wintun::make_interface(std::move(info), router); + } + + std::shared_ptr + 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 diff --git a/llarp/vpn/win32.hpp b/llarp/vpn/win32.hpp index 0fd9e0e8a..08e706fcd 100644 --- a/llarp/vpn/win32.hpp +++ b/llarp/vpn/win32.hpp @@ -16,16 +16,6 @@ namespace llarp::win32 { - namespace - { - template - 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 - GetGatewaysNotOnInterface(NetworkInterface& vpn) override - { - std::vector gateways; - - auto idx = vpn.Info().index; - using UInt_t = decltype(idx); - for (const auto& iface : Net().AllNetworkInterfaces()) - { - if (static_cast(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 - ObtainInterface(InterfaceInfo info, AbstractRouter* router) override - { - return wintun::make_interface(std::move(info), router); - } + ObtainInterface(InterfaceInfo info, AbstractRouter* router) override; std::shared_ptr - 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