VpnPlugin.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #include "pch.h"
  2. #include "VpnPlugin.h"
  3. #include "winrt/Windows.Storage.h"
  4. #include "winrt/Windows.Storage.Streams.h"
  5. #include "winrt/Windows.Storage.AccessCache.h"
  6. extern "C" void* lwip_strerr(uint8_t) {
  7. return (void*)(const char*)"";
  8. }
  9. namespace winrt::Maple_Task::implementation
  10. {
  11. using Windows::Networking::HostName;
  12. using Windows::Networking::Sockets::DatagramSocket;
  13. using Windows::Storage::Streams::IOutputStream;
  14. using namespace Windows::Networking::Vpn;
  15. using namespace Windows::Storage;
  16. using namespace Windows::Storage::AccessCache;
  17. extern "C" {
  18. typedef void(__cdecl* netstack_cb)(uint8_t*, size_t, void*);
  19. void cb(uint8_t* data, size_t size, void* outputStreamAbi) {
  20. bool needSendDummyBuffer = false;
  21. {
  22. std::lock_guard _guard{ VpnPluginInstance->m_decapQueueLock };
  23. auto& q = VpnPluginInstance->m_decapQueue;
  24. {
  25. std::vector<uint8_t> buf(size);
  26. if (memcpy_s(buf.data(), buf.capacity(), data, size)) {
  27. return;
  28. }
  29. needSendDummyBuffer = q.empty();
  30. q.emplace(buf);
  31. }
  32. }
  33. if (!needSendDummyBuffer) {
  34. return;
  35. }
  36. IOutputStream outputStream{ nullptr };
  37. winrt::attach_abi(outputStream, outputStreamAbi);
  38. try {
  39. const auto _ = outputStream.WriteAsync(dummyBuffer);
  40. }
  41. catch (...) {}
  42. winrt::detach_abi(outputStream);
  43. }
  44. }
  45. void VpnPlugin::Connect(VpnChannel const& channel)
  46. {
  47. try
  48. {
  49. ConnectCore(channel);
  50. }
  51. catch (std::exception const& ex)
  52. {
  53. channel.TerminateConnection(to_hstring(ex.what()));
  54. }
  55. }
  56. void VpnPlugin::ConnectCore(VpnChannel const& channel)
  57. {
  58. const auto localhost = HostName{ L"127.0.0.1" };
  59. DatagramSocket transport{}, backTransport{};
  60. channel.AssociateTransport(transport, nullptr);
  61. transport.BindEndpointAsync(localhost, L"").get();
  62. backTransport.BindEndpointAsync(localhost, L"").get();
  63. transport.ConnectAsync(localhost, backTransport.Information().LocalPort()).get();
  64. backTransport.ConnectAsync(localhost, transport.Information().LocalPort()).get();
  65. VpnRouteAssignment routeScope{};
  66. routeScope.ExcludeLocalSubnets(true);
  67. routeScope.Ipv4InclusionRoutes(std::vector{
  68. // 直接写 0.0.0.0/0 哪怕绑了接口也会绕回环
  69. // VpnRoute(HostName{ L"0.0.0.0" }, 0)
  70. VpnRoute(HostName{ L"0.0.0.0" }, 1),
  71. VpnRoute(HostName{ L"128.0.0.0" }, 1),
  72. });
  73. routeScope.Ipv6InclusionRoutes(std::vector{
  74. VpnRoute(HostName{L"::"}, 1),
  75. VpnRoute(HostName{L"8000::"}, 1)
  76. });
  77. // 排除代理服务器的话就会 os 10023 以一种访问权限不允许的方式做了一个访问套接字的尝试
  78. // routeScope.Ipv4ExclusionRoutes(std::vector<VpnRoute>{
  79. // VpnRoute(HostName{ L"172.25.0.0" }, 16)
  80. // });
  81. const auto outputStreamAbi = winrt::detach_abi(backTransport.OutputStream());
  82. StopLeaf();
  83. {
  84. std::lock_guard _guard{ m_decapQueueLock };
  85. while (!m_decapQueue.empty()) {
  86. m_decapQueue.pop();
  87. }
  88. }
  89. m_backTransport = backTransport;
  90. m_netStackHandle = netstack_register(cb, outputStreamAbi);
  91. if (m_netStackHandle == nullptr) {
  92. channel.TerminateConnection(L"Error initializing Leaf netstack.");
  93. return;
  94. }
  95. const auto& appData = ApplicationData::Current();
  96. const auto& configFolderPath = appData.LocalFolder().CreateFolderAsync(L"config", CreationCollisionOption::OpenIfExists).get().Path();
  97. const auto& localProperties = appData.LocalSettings().Values();
  98. const auto& outNetif = localProperties.TryLookup(NETIF_SETTING_KEY).try_as<hstring>().value_or(L"");
  99. const auto& cacheDir = appData.LocalCacheFolder().Path();
  100. if (
  101. !SetEnvironmentVariable(L"ASSET_LOCATION", configFolderPath.data())
  102. || !SetEnvironmentVariable(L"LOG_NO_COLOR", L"true")
  103. || !SetEnvironmentVariable(L"OUTBOUND_INTERFACE", outNetif.data())
  104. || !SetEnvironmentVariable(L"CACHE_LOCATION", cacheDir.data())
  105. || !SetEnvironmentVariable(L"ENABLE_IPV6", L"true")
  106. ) {
  107. channel.TerminateConnection(L"Failed to set environment variables: " + winrt::to_hstring((uint32_t)GetLastError()));
  108. return;
  109. }
  110. const auto confPathW = localProperties.TryLookup(CONFIG_PATH_SETTING_KEY).try_as<hstring>().value_or(L"");
  111. const auto confPath = winrt::to_string(confPathW);
  112. StorageFolder folder{ nullptr };
  113. try {
  114. folder = StorageApplicationPermissions::FutureAccessList().GetFolderAsync(ConfigFolderAccessListKey).get();
  115. }
  116. catch (hresult_invalid_argument const&) {}
  117. thread_local std::vector<HostName> dnsHosts{};
  118. if (folder)
  119. {
  120. if (auto const pos = confPath.rfind('\\'); pos != std::string::npos)
  121. {
  122. auto const file = folder.GetFileAsync(to_hstring(confPath.substr(pos + 1))).get();
  123. auto const text = FileIO::ReadBufferAsync(file).get();
  124. auto const len = text.Length();
  125. uint8_t* textPtr{};
  126. check_hresult(text.as<IBufferByteAccess>()->Buffer(&textPtr));
  127. m_leaf = uwp_run_leaf_with_config_content(reinterpret_cast<const char*>(textPtr), len,
  128. [](const char* dns) {
  129. dnsHosts.push_back(HostName{ to_hstring(dns) });
  130. });
  131. }
  132. else
  133. {
  134. channel.TerminateConnection(L"Config folder has been changed. Please reset the default configuration file.");
  135. return;
  136. }
  137. }
  138. else
  139. {
  140. m_leaf = uwp_run_leaf(confPath.data(), [](const char* dns) {
  141. dnsHosts.push_back(HostName{ to_hstring(dns) });
  142. });
  143. }
  144. if (m_leaf == nullptr) {
  145. 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.");
  146. StopLeaf();
  147. return;
  148. }
  149. VpnDomainNameAssignment dnsAssignment{};
  150. dnsAssignment.DomainNameList().Append(VpnDomainNameInfo(
  151. L".",
  152. VpnDomainNameType::Suffix,
  153. single_threaded_vector(std::move(dnsHosts)),
  154. single_threaded_vector(std::vector<HostName>())));
  155. channel.StartWithMainTransport(
  156. std::vector{ HostName{ L"192.168.3.1" } },
  157. std::vector{ HostName{L"fd00::2"} },
  158. nullptr,
  159. routeScope,
  160. dnsAssignment,
  161. 1500,
  162. 1512,
  163. false,
  164. transport
  165. );
  166. }
  167. void VpnPlugin::StopLeaf() {
  168. m_backTransport = nullptr;
  169. auto leafHandle = m_leaf;
  170. if (leafHandle != nullptr) {
  171. uwp_stop_leaf(leafHandle);
  172. m_leaf = nullptr;
  173. }
  174. auto netStackHandle = m_netStackHandle;
  175. if (netStackHandle != nullptr) {
  176. const auto context = netstack_release(netStackHandle);
  177. m_netStackHandle = nullptr;
  178. // Release context, which is an ABI of IOutputStream
  179. IInspectable obj{};
  180. winrt::attach_abi(obj, context);
  181. m_netStackHandle = nullptr;
  182. }
  183. }
  184. void VpnPlugin::Disconnect(VpnChannel const& channel)
  185. {
  186. try {
  187. channel.Stop();
  188. }
  189. catch (...) {}
  190. StopLeaf();
  191. }
  192. void VpnPlugin::GetKeepAlivePayload(VpnChannel const&, VpnPacketBuffer&)
  193. {
  194. }
  195. void VpnPlugin::Encapsulate([[maybe_unused]] VpnChannel const& channel, VpnPacketBufferList const& packets, VpnPacketBufferList const&)
  196. {
  197. auto packetCount = packets.Size();
  198. while (packetCount-- > 0) {
  199. const auto packet = packets.RemoveAtBegin();
  200. const auto buffer = packet.Buffer();
  201. netstack_send(m_netStackHandle, buffer.data(), static_cast<size_t>(buffer.Length()));
  202. packets.Append(packet);
  203. }
  204. }
  205. void VpnPlugin::Decapsulate(VpnChannel const& channel, [[maybe_unused]] VpnPacketBuffer const& encapBuffer, VpnPacketBufferList const& decapsulatedPackets, VpnPacketBufferList const&)
  206. {
  207. std::lock_guard _guard{ VpnPluginInstance->m_decapQueueLock };
  208. auto& q = VpnPluginInstance->m_decapQueue;
  209. while (!q.empty()) {
  210. auto&& incomingBuffer = q.front();
  211. const auto outBuffer = channel.GetVpnReceivePacketBuffer();
  212. decapsulatedPackets.Append(outBuffer);
  213. const auto outBuf = outBuffer.Buffer();
  214. const auto size = incomingBuffer.size();
  215. if (memcpy_s(outBuf.data(), outBuf.Capacity(), incomingBuffer.data(), size)) {
  216. return;
  217. }
  218. outBuf.Length(static_cast<uint32_t>(size));
  219. q.pop();
  220. }
  221. }
  222. }