VpnPlugin.cpp 7.7 KB

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