From 5fc34e643cade16daf8ea5201ee6dbbc3f9098f4 Mon Sep 17 00:00:00 2001 From: Shahzain Ali Date: Thu, 1 Dec 2022 20:26:45 +0500 Subject: [PATCH] Adding network extenstionn, fixing cmake. Botan cmake changes, cmake APPLE/IOS fixes, wireguard added, Currently removed openvpn implementation, once wireguard is stable then will add openVPN framework. Current progress is it is generating xcode project using mkdir build-ios /Users/shahzainali/Qt/6.4.1/ios/bin/qt-cmake . -B build-ios -GXcode Need to select team only for Network extension only. select AmneizaVPN to run. current issue is related to Botan. --- client/3rd/QtSsh/src/botan/botan.cmake | 8 + client/CMakeLists.txt | 47 ++- client/ios/networkextension/CMakeLists.txt | 105 +++++++ client/ios/networkextension/Info.plist | 52 ++++ client/ios/networkextension/Info.plist.in | 46 +++ ...ireGuardNetworkExtension-Bridging-Header.h | 21 ++ .../wireguard-go-version.h.in | 3 + client/platforms/ios/iostunnel.swift | 294 +++++++++--------- client/src/cmake/golang.cmake | 72 +++++ 9 files changed, 490 insertions(+), 158 deletions(-) create mode 100644 client/ios/networkextension/CMakeLists.txt create mode 100644 client/ios/networkextension/Info.plist create mode 100644 client/ios/networkextension/Info.plist.in create mode 100644 client/ios/networkextension/WireGuardNetworkExtension-Bridging-Header.h create mode 100644 client/ios/networkextension/wireguard-go-version.h.in create mode 100644 client/src/cmake/golang.cmake diff --git a/client/3rd/QtSsh/src/botan/botan.cmake b/client/3rd/QtSsh/src/botan/botan.cmake index a06d07b7..e51ce51f 100644 --- a/client/3rd/QtSsh/src/botan/botan.cmake +++ b/client/3rd/QtSsh/src/botan/botan.cmake @@ -62,4 +62,12 @@ if(IOS) # HEADERS += $$PWD/ios/iphone/botan_all.h # SOURCES += $$PWD/ios/iphone/botan_all.cpp # } + + link_directories(${CMAKE_CURRENT_LIST_DIR}/ios/iphone) + set(HEADERS ${HEADERS} ${CMAKE_CURRENT_LIST_DIR}/ios/iphone/botan_all.h) + set(SOURCES ${SOURCES} ${CMAKE_CURRENT_LIST_DIR}/ios/iphone/botan_all.cpp) + + + + endif() diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index b9d89250..8e8acb2d 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -42,7 +42,6 @@ set(BUILD_SHARED_LIBS OFF) add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/3rd/qtkeychain) set(LIBS ${LIBS} qt6keychain) - include_directories( ${CMAKE_CURRENT_LIST_DIR}/3rd/QSimpleCrypto/include ${CMAKE_CURRENT_LIST_DIR}/3rd/OpenSSL/include @@ -164,6 +163,20 @@ if(WIN32) endif() if(APPLE) + + if(NOT BUILD_OSX_APP_IDENTIFIER) + set(BUILD_OSX_APP_IDENTIFIER org.amnezia.AmneziaVPN CACHE STRING "OSX Application identifier") + endif() + if(NOT BUILD_IOS_APP_IDENTIFIER) + set(BUILD_IOS_APP_IDENTIFIER org.amnezia.AmneziaVPN CACHE STRING "iOS Application identifier") + endif() + if(NOT BUILD_IOS_GROUP_IDENTIFIER) + set(BUILD_IOS_GROUP_IDENTIFIER group.org.amnezia.AmneziaVPN.Guardian CACHE STRING "iOS Group identifier") + endif() + if(NOT BUILD_VPN_DEVELOPMENT_TEAM) + set(BUILD_VPN_DEVELOPMENT_TEAM X7UJ388FXK CACHE STRING "Amnezia VPN Development Team") + endif() + if(IOS) message("ios in mac") #do nothing, IOS is added in below @@ -215,7 +228,7 @@ if(LINUX AND NOT ANDROID) link_directories(${CMAKE_CURRENT_LIST_DIR}/platforms/linux) endif() -if(WIN32 OR APPLE OR (LINUX AND NOT ANDROID)) +if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID)) message("Client desktop build") add_compile_definitions(AMNEZIA_DESKTOP) @@ -264,9 +277,12 @@ if(ANDROID) ) endif() +qt_add_executable(${PROJECT} ${SOURCES} ${HEADERS} ${RESOURCES} ${QRC}) +qt_add_translations(${PROJECT} TS_FILES + ${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_ru.ts) + if(IOS) message("Client iOS build") - target_include_directories(${PROJECT} PRIVATE ${Qt6Gui_PRIVATE_INCLUDE_DIRS}) # CONFIG += static @@ -316,7 +332,9 @@ if(IOS) set_target_properties(${PROJECT} PROPERTIES XCODE_ATTRIBUTE_ENABLE_BITCODE "NO") - + add_subdirectory(ios/networkextension) + add_dependencies(${PROJECT} networkextension) + set_target_properties(${PROJECT} PROPERTIES XCODE_EMBED_APP_EXTENSIONS networkextension) # Q_ENABLE_BITCODE.value = NO # Q_ENABLE_BITCODE.name = ENABLE_BITCODE @@ -329,12 +347,20 @@ if(CMAKE_OSX_SYSROOT STREQUAL "iphoneos") - set_target_properties(${PROJECT} PROPERTIES XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "org.amnezia" - OUTPUT_NAME "Mozilla VPN" + set_target_properties(${PROJECT} PROPERTIES XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "org.amnezia.${PROJECT}" + OUTPUT_NAME "AmneziaVPN" XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1" XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "X7UJ388FXK" - MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/client/ios/app/Info.plist - XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Apple Distribution") + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/ios/app/Info.plist + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Apple Development") + + find_library(LIB_LIBCRYPTO NAMES "libcrypto.a" + PATHS ${PROJECT_SOURCE_DIR}/3rd/OpenSSL/lib/ios/iphone/ NO_DEFAULT_PATH) + + find_library(LIB_SSL NAMES "libssl.a" + PATHS ${PROJECT_SOURCE_DIR}/3rd/OpenSSL/lib/ios/iphone/ NO_DEFAULT_PATH) + + # set(LIBS ${LIBS} LIB_LIBCRYPTO LIB_SSL) endif() @@ -369,10 +395,7 @@ endif() # NETWORKEXTENSION=1 -qt_add_executable(${PROJECT} ${SOURCES} ${HEADERS} ${RESOURCES} ${QRC}) -qt_add_translations(${PROJECT} TS_FILES - ${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_ru.ts) if(ANDROID) add_custom_command( @@ -427,7 +450,7 @@ target_link_libraries(${PROJECT} PRIVATE Qt6::Core5Compat ${LIBS} ) -if(WIN32 OR APPLE OR (LINUX AND NOT ANDROID)) +if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID)) qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_interface.rep) qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_process_interface.rep) endif() diff --git a/client/ios/networkextension/CMakeLists.txt b/client/ios/networkextension/CMakeLists.txt new file mode 100644 index 00000000..5a8e76fb --- /dev/null +++ b/client/ios/networkextension/CMakeLists.txt @@ -0,0 +1,105 @@ +enable_language(Swift) + +add_executable(networkextension) +set_target_properties(networkextension PROPERTIES + OUTPUT_NAME "AmneziaVPNNetworkExtension" + XCODE_PRODUCT_TYPE com.apple.product-type.app-extension + BUNDLE_EXTENSION appex + MACOSX_BUNDLE ON + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in + MACOSX_BUNDLE_BUNDLE_NAME "AmneziaVPNNetworkExtension" + MACOSX_BUNDLE_BUNDLE_VERSION "${BUILD_ID}" + MACOSX_BUNDLE_COPYRIGHT "MPL-2.0" + MACOSX_BUNDLE_GUI_IDENTIFIER "${BUILD_IOS_APP_IDENTIFIER}.network-extension" + MACOSX_BUNDLE_INFO_STRING "MozillaVPNNetworkExtension" + MACOSX_BUNDLE_LONG_VERSION_STRING "${CMAKE_PROJECT_VERSION}-${BUILD_ID}" + MACOSX_BUNDLE_SHORT_VERSION_STRING "${CMAKE_PROJECT_VERSION}" + XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${BUILD_IOS_APP_IDENTIFIER}.network-extension" + XCODE_ATTRIBUTE_SWIFT_VERSION "5.0" + XCODE_ATTRIBUTE_CLANG_ENABLE_MODULES "YES" + XCODE_ATTRIBUTE_SWIFT_OBJC_BRIDGING_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/WireGuardNetworkExtension-Bridging-Header.h" + XCODE_ATTRIBUTE_SWIFT_PRECOMPILE_BRIDGING_HEADER "NO" + XCODE_ATTRIBUTE_APPLICATION_EXTENSION_API_ONLY "YES" + XCODE_ATTRIBUTE_ENABLE_BITCODE "NO" + XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS ${CMAKE_CURRENT_SOURCE_DIR}/AmneziaVPNNetworkExtension.entitlements +) + +find_library(FW_ASSETS_LIBRARY AssetsLibrary) +find_library(FW_MOBILE_CORE MobileCoreServices) +find_library(FW_UI_KIT UIKit) + +target_link_libraries(networkextension PRIVATE ${FW_ASSETS_LIBRARY}) +target_link_libraries(networkextension PRIVATE ${FW_MOBILE_CORE}) +target_link_libraries(networkextension PRIVATE ${FW_UI_KIT}) + +target_compile_options(networkextension PRIVATE -DGROUP_ID=\"${BUILD_IOS_GROUP_IDENTIFIER}\") +target_compile_options(networkextension PRIVATE -DNETWORK_EXTENSION=1) + +set(WG_APPLE_SOURCE_DIR ${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources) + +target_sources(networkextension PRIVATE + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/WireGuardAdapter.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/PacketTunnelSettingsGenerator.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/DNSResolver.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardNetworkExtension/ErrorNotifier.swift + ${WG_APPLE_SOURCE_DIR}/Shared/Keychain.swift + ${WG_APPLE_SOURCE_DIR}/Shared/Model/TunnelConfiguration+WgQuickConfig.swift + ${WG_APPLE_SOURCE_DIR}/Shared/Model/NETunnelProviderProtocol+Extension.swift + ${WG_APPLE_SOURCE_DIR}/Shared/Model/String+ArrayConversion.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/TunnelConfiguration.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/IPAddressRange.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/Endpoint.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/DNSServer.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/InterfaceConfiguration.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/PeerConfiguration.swift + ${WG_APPLE_SOURCE_DIR}/Shared/FileManager+Extension.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardKitC/x25519.c + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/Array+ConcurrentMap.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/IPAddress+AddrInfo.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/PrivateKey.swift + ${CMAKE_SOURCE_DIR}/platforms/ios/iostunnel.swift + ${CMAKE_SOURCE_DIR}/platforms/ios/iosglue.mm + ${CMAKE_SOURCE_DIR}/platforms/ios/ioslogger.swift +) + +## Build wireguard-go-version.h +execute_process( + COMMAND go list -m golang.zx2c4.com/wireguard + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources/WireGuardKitGo + OUTPUT_VARIABLE WG_VERSION_FULL +) +string(REGEX REPLACE ".*v\([0-9.]*\).*" "\\1" WG_VERSION_STRING 1.1.1) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/wireguard-go-version.h.in + ${CMAKE_CURRENT_BINARY_DIR}/wireguard-go-version.h) +target_sources(networkextension PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}/wireguard-go-version.h) + +target_include_directories(networkextension PRIVATE ${CMAKE_SOURCE_DIR}) +target_include_directories(networkextension PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) + +## HACK: Build only the first architecture, this will break universal builds +## for now, but they are already broken for mobile, which uses the arch to +## determine iOS vs. simulator builds :) +if(NOT CMAKE_OSX_ARCHITECTURES) + set(OSXARCH arm64) +else() + list(GET CMAKE_OSX_ARCHITECTURES 0 OSXARCH) +endif() + +## Build the wireguard go library +## TODO: The upstream makefile also makes an attempt to patch the golang runtime +## to provide the boot-time clock instead of an uptime clock. We should probably +## make an attempt to do the same, somehow? +include(${CMAKE_SOURCE_DIR}/src/cmake/golang.cmake) +if(OSXARCH STREQUAL "x86_64") + set(GOARCH amd64) +else() + set(GOARCH ${FIRST_OSX_ARCHITECTURE}) +endif() +add_go_library(libwg-go ${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources/WireGuardKitGo/api-apple.go + GOOS ios + GOARCH ${GOARCH} + CGO_CFLAGS -arch ${OSXARCH} + CGO_LDFLAGS -arch ${OSXARCH} +) +target_link_libraries(networkextension PRIVATE libwg-go) \ No newline at end of file diff --git a/client/ios/networkextension/Info.plist b/client/ios/networkextension/Info.plist new file mode 100644 index 00000000..6941af53 --- /dev/null +++ b/client/ios/networkextension/Info.plist @@ -0,0 +1,52 @@ + + + + + CFBundleExecutable + $(EXECUTABLE_NAME) + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + + CFBundleInfoDictionaryVersion + 6.0 + + CFBundleName + $(PRODUCT_NAME) + + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + + CFBundleShortVersionString + $(MARKETING_VERSION) + + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + + ITSAppUsesNonExemptEncryption + + + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + + CFBundleDisplayName + MozillaVPNNetworkExtension + + NSExtension + + NSExtensionPointIdentifier + com.apple.networkextension.packet-tunnel + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).PacketTunnelProvider + + + com.wireguard.ios.app_group_id + group.$(APP_ID_IOS) + + com.wireguard.macos.app_group_id + $(DEVELOPMENT_TEAM).group.$(APP_ID_MACOS) + + \ No newline at end of file diff --git a/client/ios/networkextension/Info.plist.in b/client/ios/networkextension/Info.plist.in new file mode 100644 index 00000000..54d9d8d9 --- /dev/null +++ b/client/ios/networkextension/Info.plist.in @@ -0,0 +1,46 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + + CFBundleIdentifier + ${MACOSX_BUNDLE_GUI_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${MACOSX_BUNDLE_BUNDLE_NAME} + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + ${MACOSX_BUNDLE_SHORT_VERSION_STRING} + CFBundleVersion + ${MACOSX_BUNDLE_BUNDLE_VERSION} + + ITSAppUsesNonExemptEncryption + + + LSMinimumSystemVersion + ${CMAKE_OSX_DEPLOYMENT_TARGET} + + CFBundleDisplayName + ${MACOSX_BUNDLE_INFO_STRING} + + NSExtension + + NSExtensionPointIdentifier + com.apple.networkextension.packet-tunnel + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).PacketTunnelProvider + + + com.wireguard.ios.app_group_id + group.${BUILD_IOS_APP_IDENTIFIER} + + com.wireguard.macos.app_group_id + ${BUILD_VPN_DEVELOPMENT_TEAM}.group.${BUILD_OSX_APP_IDENTIFIER} + + \ No newline at end of file diff --git a/client/ios/networkextension/WireGuardNetworkExtension-Bridging-Header.h b/client/ios/networkextension/WireGuardNetworkExtension-Bridging-Header.h new file mode 100644 index 00000000..03a987ad --- /dev/null +++ b/client/ios/networkextension/WireGuardNetworkExtension-Bridging-Header.h @@ -0,0 +1,21 @@ +#include "wireguard-go-version.h" +#include "3rd/wireguard-apple/Sources/WireGuardKitGo/wireguard.h" +#include "3rd/wireguard-apple/Sources/WireGuardKitC/WireGuardKitC.h" + +#include +#include + +#define WG_KEY_LEN (32) +#define WG_KEY_LEN_BASE64 (45) +#define WG_KEY_LEN_HEX (65) + +void key_to_base64(char base64[WG_KEY_LEN_BASE64], + const uint8_t key[WG_KEY_LEN]); +bool key_from_base64(uint8_t key[WG_KEY_LEN], const char* base64); + +void key_to_hex(char hex[WG_KEY_LEN_HEX], const uint8_t key[WG_KEY_LEN]); +bool key_from_hex(uint8_t key[WG_KEY_LEN], const char* hex); + +bool key_eq(const uint8_t key1[WG_KEY_LEN], const uint8_t key2[WG_KEY_LEN]); + +void write_msg_to_log(const char* tag, const char* msg); diff --git a/client/ios/networkextension/wireguard-go-version.h.in b/client/ios/networkextension/wireguard-go-version.h.in new file mode 100644 index 00000000..860bc3c3 --- /dev/null +++ b/client/ios/networkextension/wireguard-go-version.h.in @@ -0,0 +1,3 @@ +#ifndef WIREGUARD_GO_VERSION +#define WIREGUARD_GO_VERSION "@WG_VERSION_STRING@" +#endif // WIREGUARD_GO_VERSION \ No newline at end of file diff --git a/client/platforms/ios/iostunnel.swift b/client/platforms/ios/iostunnel.swift index 5209306d..b273f9f4 100644 --- a/client/platforms/ios/iostunnel.swift +++ b/client/platforms/ios/iostunnel.swift @@ -2,7 +2,7 @@ import Foundation import NetworkExtension import os import Darwin -import OpenVPNAdapter +//import OpenVPNAdapter //import Tun2socks enum TunnelProtoType: String { @@ -48,11 +48,11 @@ class PacketTunnelProvider: NEPacketTunnelProvider { } }() - private lazy var ovpnAdapter: OpenVPNAdapter = { - let adapter = OpenVPNAdapter() - adapter.delegate = self - return adapter - }() +// private lazy var ovpnAdapter: OpenVPNAdapter = { +// let adapter = OpenVPNAdapter() +// adapter.delegate = self +// return adapter +// }() private var shadowSocksConfig: Data? = nil private var openVPNConfig: Data? = nil @@ -70,7 +70,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider { // private var session: NWUDPSession? = nil // private var observer: AnyObject? - let vpnReachability = OpenVPNReachability() +// let vpnReachability = OpenVPNReachability() var startHandler: ((Error?) -> Void)? var stopHandler: (() -> Void)? @@ -97,7 +97,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider { errorNotifier: errorNotifier, completionHandler: completionHandler) case .openvpn: - startOpenVPN(completionHandler: completionHandler) + break + //startOpenVPN(completionHandler: completionHandler) case .shadowsocks: break // startShadowSocks(completionHandler: completionHandler) @@ -111,7 +112,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider { case .wireguard: stopWireguard(with: reason, completionHandler: completionHandler) case .openvpn: - stopOpenVPN(with: reason, completionHandler: completionHandler) + break + // stopOpenVPN(with: reason, completionHandler: completionHandler) case .shadowsocks: break // stopShadowSocks(with: reason, completionHandler: completionHandler) @@ -187,17 +189,17 @@ class PacketTunnelProvider: NEPacketTunnelProvider { } } - private func startOpenVPN(completionHandler: @escaping (Error?) -> Void) { - guard let protocolConfiguration = self.protocolConfiguration as? NETunnelProviderProtocol, - let providerConfiguration = protocolConfiguration.providerConfiguration, - let ovpnConfiguration: Data = providerConfiguration[Constants.ovpnConfigKey] as? Data else { - // TODO: handle errors properly - wg_log(.error, message: "Can't start startOpenVPN()") - return - } - - setupAndlaunchOpenVPN(withConfig: ovpnConfiguration, completionHandler: completionHandler) - } +// private func startOpenVPN(completionHandler: @escaping (Error?) -> Void) { +// guard let protocolConfiguration = self.protocolConfiguration as? NETunnelProviderProtocol, +// let providerConfiguration = protocolConfiguration.providerConfiguration, +// let ovpnConfiguration: Data = providerConfiguration[Constants.ovpnConfigKey] as? Data else { +// // TODO: handle errors properly +// wg_log(.error, message: "Can't start startOpenVPN()") +// return +// } +// +// setupAndlaunchOpenVPN(withConfig: ovpnConfiguration, completionHandler: completionHandler) +// } /* private func startShadowSocks(completionHandler: @escaping (Error?) -> Void) { guard let protocolConfiguration = self.protocolConfiguration as? NETunnelProviderProtocol, @@ -236,13 +238,13 @@ class PacketTunnelProvider: NEPacketTunnelProvider { } } - private func stopOpenVPN(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { - stopHandler = completionHandler - if vpnReachability.isTracking { - vpnReachability.stopTracking() - } - ovpnAdapter.disconnect() - } +// private func stopOpenVPN(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { +// stopHandler = completionHandler +// if vpnReachability.isTracking { +// vpnReachability.stopTracking() +// } +// ovpnAdapter.disconnect() +// } /* private func stopShadowSocks(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { stopOpenVPN(with: reason) { [weak self] in @@ -686,47 +688,47 @@ class PacketTunnelProvider: NEPacketTunnelProvider { } } */ - private func setupAndlaunchOpenVPN(withConfig ovpnConfiguration: Data, withShadowSocks viaSS: Bool = false, completionHandler: @escaping (Error?) -> Void) { - wg_log(.info, message: "Inside setupAndlaunchOpenVPN()") - let str = String(decoding: ovpnConfiguration, as: UTF8.self) - wg_log(.info, message: "OPENVPN config: \(str)") - - let configuration = OpenVPNConfiguration() - configuration.fileContent = ovpnConfiguration - if viaSS { -// configuration.settings = [ -// "remote": "137.74.6.148 1194", -// "proto": "tcp", -// "link-mtu": "1480", -// "tun-mtu": "1460", -// ] - } - let evaluation: OpenVPNConfigurationEvaluation - do { - evaluation = try ovpnAdapter.apply(configuration: configuration) - } catch { - completionHandler(error) - return - } - - if !evaluation.autologin { - wg_log(.info, message: "Implement login with user credentials") - } - - vpnReachability.startTracking { [weak self] status in - guard status == .reachableViaWiFi else { return } - self?.ovpnAdapter.reconnect(afterTimeInterval: 5) - } - - startHandler = completionHandler - ovpnAdapter.connect(using: packetFlow) - - let ifaces = Interface.allInterfaces() - .filter { $0.family == .ipv4 } - .map { iface in iface.name } - - wg_log(.error, message: "Available TUN Interfaces: \(ifaces)") - } +// private func setupAndlaunchOpenVPN(withConfig ovpnConfiguration: Data, withShadowSocks viaSS: Bool = false, completionHandler: @escaping (Error?) -> Void) { +// wg_log(.info, message: "Inside setupAndlaunchOpenVPN()") +// let str = String(decoding: ovpnConfiguration, as: UTF8.self) +// wg_log(.info, message: "OPENVPN config: \(str)") +// +// let configuration = OpenVPNConfiguration() +// configuration.fileContent = ovpnConfiguration +// if viaSS { +//// configuration.settings = [ +//// "remote": "137.74.6.148 1194", +//// "proto": "tcp", +//// "link-mtu": "1480", +//// "tun-mtu": "1460", +//// ] +// } +// let evaluation: OpenVPNConfigurationEvaluation +// do { +// evaluation = try ovpnAdapter.apply(configuration: configuration) +// } catch { +// completionHandler(error) +// return +// } +// +// if !evaluation.autologin { +// wg_log(.info, message: "Implement login with user credentials") +// } +// +// vpnReachability.startTracking { [weak self] status in +// guard status == .reachableViaWiFi else { return } +// self?.ovpnAdapter.reconnect(afterTimeInterval: 5) +// } +// +// startHandler = completionHandler +// ovpnAdapter.connect(using: packetFlow) +// +// let ifaces = Interface.allInterfaces() +// .filter { $0.family == .ipv4 } +// .map { iface in iface.name } +// +// wg_log(.error, message: "Available TUN Interfaces: \(ifaces)") +// } // MARK: -- Network observing methods @@ -796,87 +798,87 @@ extension WireGuardLogLevel { } } -extension NEPacketTunnelFlow: OpenVPNAdapterPacketFlow {} +//extension NEPacketTunnelFlow: OpenVPNAdapterPacketFlow {} /* extension NEPacketTunnelFlow: ShadowSocksAdapterPacketFlow {} */ -extension PacketTunnelProvider: OpenVPNAdapterDelegate { - - // OpenVPNAdapter calls this delegate method to configure a VPN tunnel. - // `completionHandler` callback requires an object conforming to `OpenVPNAdapterPacketFlow` - // protocol if the tunnel is configured without errors. Otherwise send nil. - // `OpenVPNAdapterPacketFlow` method signatures are similar to `NEPacketTunnelFlow` so - // you can just extend that class to adopt `OpenVPNAdapterPacketFlow` protocol and - // send `self.packetFlow` to `completionHandler` callback. - func openVPNAdapter( - _ openVPNAdapter: OpenVPNAdapter, - configureTunnelWithNetworkSettings networkSettings: NEPacketTunnelNetworkSettings?, - completionHandler: @escaping (Error?) -> Void - ) { - // In order to direct all DNS queries first to the VPN DNS servers before the primary DNS servers - // send empty string to NEDNSSettings.matchDomains - networkSettings?.dnsSettings?.matchDomains = [""] - - // Set the network settings for the current tunneling session. - setTunnelNetworkSettings(networkSettings, completionHandler: completionHandler) - } - - // Process events returned by the OpenVPN library - func openVPNAdapter( - _ openVPNAdapter: OpenVPNAdapter, - handleEvent event: - OpenVPNAdapterEvent, message: String? - ) { - switch event { - case .connected: - if reasserting { - reasserting = false - } - - guard let startHandler = startHandler else { return } - - startHandler(nil) - self.startHandler = nil - case .disconnected: - guard let stopHandler = stopHandler else { return } - - if vpnReachability.isTracking { - vpnReachability.stopTracking() - } - - stopHandler() - self.stopHandler = nil - case .reconnecting: - reasserting = true - default: - break - } - } - - // Handle errors thrown by the OpenVPN library - func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleError error: Error) { - // Handle only fatal errors - guard let fatal = (error as NSError).userInfo[OpenVPNAdapterErrorFatalKey] as? Bool, - fatal == true else { return } - - if vpnReachability.isTracking { - vpnReachability.stopTracking() - } - - if let startHandler = startHandler { - startHandler(error) - self.startHandler = nil - } else { - cancelTunnelWithError(error) - } - } - - // Use this method to process any log message returned by OpenVPN library. - func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleLogMessage logMessage: String) { - // Handle log messages - wg_log(.info, message: logMessage) - } -} +//extension PacketTunnelProvider: OpenVPNAdapterDelegate { +// +// // OpenVPNAdapter calls this delegate method to configure a VPN tunnel. +// // `completionHandler` callback requires an object conforming to `OpenVPNAdapterPacketFlow` +// // protocol if the tunnel is configured without errors. Otherwise send nil. +// // `OpenVPNAdapterPacketFlow` method signatures are similar to `NEPacketTunnelFlow` so +// // you can just extend that class to adopt `OpenVPNAdapterPacketFlow` protocol and +// // send `self.packetFlow` to `completionHandler` callback. +// func openVPNAdapter( +// _ openVPNAdapter: OpenVPNAdapter, +// configureTunnelWithNetworkSettings networkSettings: NEPacketTunnelNetworkSettings?, +// completionHandler: @escaping (Error?) -> Void +// ) { +// // In order to direct all DNS queries first to the VPN DNS servers before the primary DNS servers +// // send empty string to NEDNSSettings.matchDomains +// networkSettings?.dnsSettings?.matchDomains = [""] +// +// // Set the network settings for the current tunneling session. +// setTunnelNetworkSettings(networkSettings, completionHandler: completionHandler) +// } +// +// // Process events returned by the OpenVPN library +// func openVPNAdapter( +// _ openVPNAdapter: OpenVPNAdapter, +// handleEvent event: +// OpenVPNAdapterEvent, message: String? +// ) { +// switch event { +// case .connected: +// if reasserting { +// reasserting = false +// } +// +// guard let startHandler = startHandler else { return } +// +// startHandler(nil) +// self.startHandler = nil +// case .disconnected: +// guard let stopHandler = stopHandler else { return } +// +// if vpnReachability.isTracking { +// vpnReachability.stopTracking() +// } +// +// stopHandler() +// self.stopHandler = nil +// case .reconnecting: +// reasserting = true +// default: +// break +// } +// } +// +// // Handle errors thrown by the OpenVPN library +// func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleError error: Error) { +// // Handle only fatal errors +// guard let fatal = (error as NSError).userInfo[OpenVPNAdapterErrorFatalKey] as? Bool, +// fatal == true else { return } +// +// if vpnReachability.isTracking { +// vpnReachability.stopTracking() +// } +// +// if let startHandler = startHandler { +// startHandler(error) +// self.startHandler = nil +// } else { +// cancelTunnelWithError(error) +// } +// } +// +// // Use this method to process any log message returned by OpenVPN library. +// func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleLogMessage logMessage: String) { +// // Handle log messages +// wg_log(.info, message: logMessage) +// } +//} /* extension PacketTunnelProvider: Tun2socksTunWriterProtocol { func write(_ p0: Data?, n: UnsafeMutablePointer?) throws { diff --git a/client/src/cmake/golang.cmake b/client/src/cmake/golang.cmake new file mode 100644 index 00000000..2e16db70 --- /dev/null +++ b/client/src/cmake/golang.cmake @@ -0,0 +1,72 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +## Find the absolute path to the go build tool. +find_program(GOLANG_BUILD_TOOL NAMES go REQUIRED) + +## Create a library target built from a golang c-archive. +function(add_go_library GOTARGET SOURCE) + cmake_parse_arguments(GOLANG + "" + "GOOS;GOARCH" + "CGO_CFLAGS;CGO_LDFLAGS" + ${ARGN}) + get_filename_component(SRC_NAME ${SOURCE} NAME) + get_filename_component(DIR_NAME ${SOURCE} DIRECTORY) + get_filename_component(DIR_ABSOLUTE ${DIR_NAME} ABSOLUTE) + + file(GLOB_RECURSE SRC_DEPS ${DIR_NAME}/*.go) + set(HEADER_NAME "${GOTARGET}.h") + set(ARCHIVE_NAME "${GOTARGET}${CMAKE_STATIC_LIBRARY_SUFFIX}") + + set(GOCACHE ${CMAKE_BINARY_DIR}/go-cache) + set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${CMAKE_BINARY_DIR}/go-cache) + set(GOFLAGS -buildmode=c-archive -trimpath -v) + if(IS_DIRECTORY ${DIR_NAME}/vendor) + set(GOFLAGS ${GOFLAGS} -mod vendor) + endif() + + ## Add extras to the CGO compiler and linker flags. + execute_process(OUTPUT_VARIABLE DEFAULT_CGO_CFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND ${GOLANG_BUILD_TOOL} env CGO_CFLAGS) + execute_process(OUTPUT_VARIABLE DEFAULT_CGO_LDFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND ${GOLANG_BUILD_TOOL} env CGO_LDFLAGS) + separate_arguments(DEFAULT_CGO_CFLAGS NATIVE_COMMAND ${DEFAULT_CGO_CFLAGS}) + separate_arguments(DEFAULT_CGO_LDFLAGS NATIVE_COMMAND ${DEFAULT_CGO_LDFLAGS}) + list(PREPEND GOLANG_CGO_CFLAGS ${DEFAULT_CGO_CFLAGS}) + list(PREPEND GOLANG_CGO_LDFLAGS ${DEFAULT_CGO_LDFLAGS}) + if(NOT GOLANG_GOOS) + execute_process(OUTPUT_VARIABLE GOLANG_GOOS OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND ${GOLANG_BUILD_TOOL} env GOOS) + endif() + if(NOT GOLANG_GOARCH) + execute_process(OUTPUT_VARIABLE GOLANG_GOARCH OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND ${GOLANG_BUILD_TOOL} env GOARCH) + endif() + + if(APPLE AND CMAKE_OSX_SYSROOT) + execute_process(OUTPUT_VARIABLE SDKROOT OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND xcrun --sdk ${CMAKE_OSX_SYSROOT} --show-sdk-path) + list(APPEND GOLANG_CGO_CFLAGS -isysroot ${SDKROOT}) + list(APPEND GOLANG_CGO_LDFLAGS -isysroot ${SDKROOT}) + endif() + + ## The actual commands that do the building. + add_custom_target(golang_${GOTARGET} + BYPRODUCTS ${ARCHIVE_NAME} ${HEADER_NAME} + WORKING_DIRECTORY ${DIR_ABSOLUTE} + SOURCES ${SRC_DEPS} ${DIR_NAME}/go.mod + COMMAND ${CMAKE_COMMAND} -E env GOCACHE=${GOCACHE} + CGO_ENABLED=1 + CGO_CFLAGS="${GOLANG_CGO_CFLAGS}" + CGO_LDFLAGS="${GOLANG_CGO_LDFLAGS}" + GOOS="${GOLANG_GOOS}" + GOARCH="${GOLANG_GOARCH}" + ${GOLANG_BUILD_TOOL} build ${GOFLAGS} -o ${CMAKE_CURRENT_BINARY_DIR}/${ARCHIVE_NAME} ${SRC_NAME} + ) + set_target_properties(golang_${GOTARGET} PROPERTIES FOLDER "Libs") + + ## Wrap up the built library as an imported target. + add_library(${GOTARGET} STATIC IMPORTED GLOBAL) + add_dependencies(${GOTARGET} golang_${GOTARGET}) + set_target_properties(${GOTARGET} PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR} + INTERFACE_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${HEADER_NAME} + IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/${ARCHIVE_NAME}) +endfunction(add_go_library) \ No newline at end of file