VpnPlugin.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #include "pch.h"
  2. #include "VpnPlugin.h"
  3. #include "winrt/Windows.Storage.h"
  4. #include "winrt/Windows.Storage.Streams.h"
  5. extern "C" void* lwip_strerr(uint8_t) {
  6. return "";
  7. }
  8. namespace winrt::Maple_Task::implementation
  9. {
  10. using Windows::Networking::HostName;
  11. using Windows::Networking::Sockets::DatagramSocket;
  12. using Windows::Storage::Streams::IOutputStream;
  13. using namespace Windows::Networking::Vpn;
  14. using namespace Windows::Storage;
  15. void VpnPlugin::Connect(VpnChannel const& channel)
  16. {
  17. const auto localhost = HostName{ L"127.0.0.1" };
  18. DatagramSocket transport{}, backTransport{};
  19. channel.AssociateTransport(transport, nullptr);
  20. transport.BindEndpointAsync(localhost, L"").get();
  21. backTransport.BindEndpointAsync(localhost, L"").get();
  22. transport.ConnectAsync(localhost, backTransport.Information().LocalPort()).get();
  23. backTransport.ConnectAsync(localhost, transport.Information().LocalPort()).get();
  24. VpnRouteAssignment routeScope{};
  25. routeScope.ExcludeLocalSubnets(true);
  26. routeScope.Ipv4InclusionRoutes(std::vector<VpnRoute>{
  27. // 直接写 0.0.0.0/0 哪怕绑了接口也会绕回环
  28. // VpnRoute(HostName{ L"0.0.0.0" }, 0)
  29. VpnRoute(HostName{ L"0.0.0.0" }, 1),
  30. VpnRoute(HostName{ L"128.0.0.0" }, 1),
  31. });
  32. // 排除代理服务器的话就会 os 10023 以一种访问权限不允许的方式做了一个访问套接字的尝试
  33. // routeScope.Ipv4ExclusionRoutes(std::vector<VpnRoute>{
  34. // VpnRoute(HostName{ L"172.25.0.0" }, 16)
  35. // });
  36. const auto outputStreamAbi = winrt::detach_abi(backTransport.OutputStream());
  37. StopLeaf();
  38. {
  39. std::lock_guard _guard{ m_decapQueueLock };
  40. while (!m_decapQueue.empty()) {
  41. m_decapQueue.pop();
  42. }
  43. }
  44. m_backTransport = backTransport;
  45. m_netStackHandle = netstack_register([](uint8_t* data, size_t size, void* outputStreamAbi) {
  46. bool needSendDummyBuffer = false;
  47. {
  48. std::lock_guard _guard{ VpnPluginInstance->m_decapQueueLock };
  49. auto& q = VpnPluginInstance->m_decapQueue;
  50. {
  51. std::vector<uint8_t> buf(size);
  52. if (memcpy_s(buf.data(), buf.capacity(), data, size)) {
  53. return;
  54. }
  55. needSendDummyBuffer = q.empty();
  56. q.emplace(buf);
  57. }
  58. }
  59. if (!needSendDummyBuffer) {
  60. return;
  61. }
  62. IOutputStream outputStream{ nullptr };
  63. winrt::attach_abi(outputStream, outputStreamAbi);
  64. try {
  65. const auto _ = outputStream.WriteAsync(dummyBuffer);
  66. }
  67. catch (...) {}
  68. winrt::detach_abi(outputStream);
  69. }, outputStreamAbi);
  70. if (m_netStackHandle == nullptr) {
  71. channel.TerminateConnection(L"Error initializing Leaf netstack.");
  72. return;
  73. }
  74. const auto& configFolderPath = Windows::Storage::ApplicationData::Current().LocalFolder().CreateFolderAsync(L"config", CreationCollisionOption::OpenIfExists).get().Path();
  75. if (!SetEnvironmentVariable(L"ASSET_LOCATION", configFolderPath.data())) {
  76. channel.TerminateConnection(L"Failed to set asset location: " + winrt::to_hstring((uint32_t)GetLastError()));
  77. return;
  78. }
  79. const auto& localProperties = ApplicationData::Current().LocalSettings().Values();
  80. const auto& confPathW = localProperties.TryLookup(CONFIG_PATH_SETTING_KEY).try_as<hstring>().value_or(L"");
  81. const auto& outNetifW = localProperties.TryLookup(NETIF_SETTING_KEY).try_as<hstring>().value_or(L"");
  82. const auto& confPath = winrt::to_string(confPathW);
  83. const auto& outNetif = winrt::to_string(outNetifW);
  84. thread_local std::vector<HostName> dnsHosts{};
  85. m_leaf = run_leaf(confPath.data(), outNetif == "" ? nullptr : outNetif.data(), [](const char* dns) {
  86. dnsHosts.push_back(HostName{ to_hstring(dns) });
  87. });
  88. if (m_leaf == nullptr) {
  89. channel.TerminateConnection(L"Error initializing Leaf runtime.\r\nPlease check your configuration file and default interface.");
  90. StopLeaf();
  91. return;
  92. }
  93. VpnDomainNameAssignment dnsAssignment{};
  94. dnsAssignment.DomainNameList().Append(VpnDomainNameInfo(
  95. L".",
  96. VpnDomainNameType::Suffix,
  97. single_threaded_vector(std::move(dnsHosts)),
  98. single_threaded_vector(std::vector<HostName>())));
  99. channel.StartWithMainTransport(
  100. std::vector<HostName> { HostName{ L"192.168.3.1" } },
  101. nullptr,
  102. nullptr,
  103. routeScope,
  104. dnsAssignment,
  105. 1500,
  106. 1512,
  107. false,
  108. transport
  109. );
  110. }
  111. void VpnPlugin::StopLeaf() {
  112. m_backTransport = nullptr;
  113. auto leafHandle = m_leaf;
  114. if (leafHandle != nullptr) {
  115. stop_leaf(leafHandle);
  116. m_leaf = nullptr;
  117. }
  118. auto netStackHandle = m_netStackHandle;
  119. if (netStackHandle != nullptr) {
  120. const auto context = netstack_release(netStackHandle);
  121. m_netStackHandle = nullptr;
  122. // Release context, which is an ABI of IOutputStream
  123. IInspectable obj{};
  124. winrt::attach_abi(obj, context);
  125. m_netStackHandle = nullptr;
  126. }
  127. }
  128. void VpnPlugin::Disconnect(VpnChannel const& channel)
  129. {
  130. try {
  131. channel.Stop();
  132. }
  133. catch (...) {}
  134. StopLeaf();
  135. }
  136. void VpnPlugin::GetKeepAlivePayload(VpnChannel const&, VpnPacketBuffer&)
  137. {
  138. }
  139. void VpnPlugin::Encapsulate([[maybe_unused]] VpnChannel const& channel, VpnPacketBufferList const& packets, VpnPacketBufferList const&)
  140. {
  141. auto packetCount = packets.Size();
  142. while (packetCount-- > 0) {
  143. const auto packet = packets.RemoveAtBegin();
  144. const auto buffer = packet.Buffer();
  145. netstack_send(m_netStackHandle, buffer.data(), static_cast<size_t>(buffer.Length()));
  146. packets.Append(packet);
  147. }
  148. }
  149. void VpnPlugin::Decapsulate(VpnChannel const& channel, [[maybe_unused]] VpnPacketBuffer const& encapBuffer, VpnPacketBufferList const& decapsulatedPackets, VpnPacketBufferList const&)
  150. {
  151. std::lock_guard _guard{ VpnPluginInstance->m_decapQueueLock };
  152. auto& q = VpnPluginInstance->m_decapQueue;
  153. while (!q.empty()) {
  154. auto&& incomingBuffer = q.front();
  155. const auto outBuffer = channel.GetVpnReceivePacketBuffer();
  156. decapsulatedPackets.Append(outBuffer);
  157. const auto outBuf = outBuffer.Buffer();
  158. const auto size = incomingBuffer.size();
  159. if (memcpy_s(outBuf.data(), outBuf.Capacity(), incomingBuffer.data(), size)) {
  160. return;
  161. }
  162. outBuf.Length(static_cast<uint32_t>(size));
  163. q.pop();
  164. }
  165. }
  166. }