parent
eeeb2805c5
commit
760f935965
10 changed files with 285 additions and 3 deletions
|
@ -1 +1 @@
|
||||||
Subproject commit ea49bf8796afbc5bd70a0f98f4d99c9ea4792d80
|
Subproject commit ff8445c8aa1cda38497bb6f6cb0e520f5a3c8de0
|
2
client/3rd/amneziawg-apple
vendored
2
client/3rd/amneziawg-apple
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 0829e99ea9f4508fd1d4742546b62145d17587bb
|
Subproject commit 76e7db556a6d7e2582f9481df91db188a46c009c
|
|
@ -285,6 +285,7 @@ bool ContainerProps::isSupportedByCurrentPlatform(DockerContainer c)
|
||||||
case DockerContainer::WireGuard: return true;
|
case DockerContainer::WireGuard: return true;
|
||||||
case DockerContainer::OpenVpn: return true;
|
case DockerContainer::OpenVpn: return true;
|
||||||
case DockerContainer::Awg: return true;
|
case DockerContainer::Awg: return true;
|
||||||
|
case DockerContainer::Xray: return true;
|
||||||
case DockerContainer::Cloak:
|
case DockerContainer::Cloak:
|
||||||
return true;
|
return true;
|
||||||
// case DockerContainer::ShadowSocks: return true;
|
// case DockerContainer::ShadowSocks: return true;
|
||||||
|
|
|
@ -50,10 +50,12 @@ set_target_properties("networkextension" PROPERTIES
|
||||||
find_library(FW_ASSETS_LIBRARY AssetsLibrary)
|
find_library(FW_ASSETS_LIBRARY AssetsLibrary)
|
||||||
find_library(FW_MOBILE_CORE MobileCoreServices)
|
find_library(FW_MOBILE_CORE MobileCoreServices)
|
||||||
find_library(FW_UI_KIT UIKit)
|
find_library(FW_UI_KIT UIKit)
|
||||||
|
find_library(FW_LIBRESOLV libresolv.9.tbd)
|
||||||
|
|
||||||
target_link_libraries(networkextension PRIVATE ${FW_ASSETS_LIBRARY})
|
target_link_libraries(networkextension PRIVATE ${FW_ASSETS_LIBRARY})
|
||||||
target_link_libraries(networkextension PRIVATE ${FW_MOBILE_CORE})
|
target_link_libraries(networkextension PRIVATE ${FW_MOBILE_CORE})
|
||||||
target_link_libraries(networkextension PRIVATE ${FW_UI_KIT})
|
target_link_libraries(networkextension PRIVATE ${FW_UI_KIT})
|
||||||
|
target_link_libraries(networkextension PRIVATE ${FW_LIBRESOLV})
|
||||||
|
|
||||||
target_compile_options(networkextension PRIVATE -DGROUP_ID=\"${BUILD_IOS_GROUP_IDENTIFIER}\")
|
target_compile_options(networkextension PRIVATE -DGROUP_ID=\"${BUILD_IOS_GROUP_IDENTIFIER}\")
|
||||||
target_compile_options(networkextension PRIVATE -DNETWORK_EXTENSION=1)
|
target_compile_options(networkextension PRIVATE -DNETWORK_EXTENSION=1)
|
||||||
|
@ -80,12 +82,14 @@ target_sources(networkextension PRIVATE
|
||||||
${WG_APPLE_SOURCE_DIR}/WireGuardKit/Array+ConcurrentMap.swift
|
${WG_APPLE_SOURCE_DIR}/WireGuardKit/Array+ConcurrentMap.swift
|
||||||
${WG_APPLE_SOURCE_DIR}/WireGuardKit/IPAddress+AddrInfo.swift
|
${WG_APPLE_SOURCE_DIR}/WireGuardKit/IPAddress+AddrInfo.swift
|
||||||
${WG_APPLE_SOURCE_DIR}/WireGuardKit/PrivateKey.swift
|
${WG_APPLE_SOURCE_DIR}/WireGuardKit/PrivateKey.swift
|
||||||
|
${CLIENT_ROOT_DIR}/platforms/ios/HevSocksTunnel.swift
|
||||||
${CLIENT_ROOT_DIR}/platforms/ios/NELogController.swift
|
${CLIENT_ROOT_DIR}/platforms/ios/NELogController.swift
|
||||||
${CLIENT_ROOT_DIR}/platforms/ios/Log.swift
|
${CLIENT_ROOT_DIR}/platforms/ios/Log.swift
|
||||||
${CLIENT_ROOT_DIR}/platforms/ios/LogRecord.swift
|
${CLIENT_ROOT_DIR}/platforms/ios/LogRecord.swift
|
||||||
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider.swift
|
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider.swift
|
||||||
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider+WireGuard.swift
|
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider+WireGuard.swift
|
||||||
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider+OpenVPN.swift
|
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider+OpenVPN.swift
|
||||||
|
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider+Xray.swift
|
||||||
${CLIENT_ROOT_DIR}/platforms/ios/WGConfig.swift
|
${CLIENT_ROOT_DIR}/platforms/ios/WGConfig.swift
|
||||||
${CLIENT_ROOT_DIR}/platforms/ios/iosglue.mm
|
${CLIENT_ROOT_DIR}/platforms/ios/iosglue.mm
|
||||||
)
|
)
|
||||||
|
@ -114,3 +118,5 @@ target_include_directories(networkextension PRIVATE ${CLIENT_ROOT_DIR})
|
||||||
target_include_directories(networkextension PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
target_include_directories(networkextension PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
target_link_libraries(networkextension PRIVATE ${CLIENT_ROOT_DIR}/3rd-prebuilt/3rd-prebuilt/wireguard/ios/arm64/libwg-go.a)
|
target_link_libraries(networkextension PRIVATE ${CLIENT_ROOT_DIR}/3rd-prebuilt/3rd-prebuilt/wireguard/ios/arm64/libwg-go.a)
|
||||||
|
|
||||||
|
target_link_libraries(networkextension PRIVATE ${CLIENT_ROOT_DIR}/3rd-prebuilt/3rd-prebuilt/xray/HevSocks5Tunnel.xcframework)
|
||||||
|
|
73
client/platforms/ios/HevSocksTunnel.swift
Normal file
73
client/platforms/ios/HevSocksTunnel.swift
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
import HevSocks5Tunnel
|
||||||
|
|
||||||
|
public enum Socks5Tunnel {
|
||||||
|
|
||||||
|
private static var tunnelFileDescriptor: Int32? {
|
||||||
|
var ctlInfo = ctl_info()
|
||||||
|
withUnsafeMutablePointer(to: &ctlInfo.ctl_name) {
|
||||||
|
$0.withMemoryRebound(to: CChar.self, capacity: MemoryLayout.size(ofValue: $0.pointee)) {
|
||||||
|
_ = strcpy($0, "com.apple.net.utun_control")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for fd: Int32 in 0...1024 {
|
||||||
|
var addr = sockaddr_ctl()
|
||||||
|
var ret: Int32 = -1
|
||||||
|
var len = socklen_t(MemoryLayout.size(ofValue: addr))
|
||||||
|
withUnsafeMutablePointer(to: &addr) {
|
||||||
|
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
|
||||||
|
ret = getpeername(fd, $0, &len)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ret != 0 || addr.sc_family != AF_SYSTEM {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if ctlInfo.ctl_id == 0 {
|
||||||
|
ret = ioctl(fd, CTLIOCGINFO, &ctlInfo)
|
||||||
|
if ret != 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if addr.sc_id == ctlInfo.ctl_id {
|
||||||
|
return fd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
private static var interfaceName: String? {
|
||||||
|
guard let tunnelFileDescriptor = self.tunnelFileDescriptor else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var buffer = [UInt8](repeating: 0, count: Int(IFNAMSIZ))
|
||||||
|
return buffer.withUnsafeMutableBufferPointer { mutableBufferPointer in
|
||||||
|
guard let baseAddress = mutableBufferPointer.baseAddress else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var ifnameSize = socklen_t(IFNAMSIZ)
|
||||||
|
let result = getsockopt(
|
||||||
|
tunnelFileDescriptor,
|
||||||
|
2 /* SYSPROTO_CONTROL */,
|
||||||
|
2 /* UTUN_OPT_IFNAME */,
|
||||||
|
baseAddress,
|
||||||
|
&ifnameSize
|
||||||
|
)
|
||||||
|
if result == 0 {
|
||||||
|
return String(cString: baseAddress)
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
public static func run(withConfig filePath: String) -> Int32 {
|
||||||
|
guard let fileDescriptor = self.tunnelFileDescriptor else {
|
||||||
|
fatalError("Get tunnel file descriptor failed.")
|
||||||
|
}
|
||||||
|
return hev_socks5_tunnel_main(filePath.cString(using: .utf8), fileDescriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func quit() {
|
||||||
|
hev_socks5_tunnel_quit()
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,6 +13,10 @@ public func ovpnLog(_ type: OSLogType, title: String = "", message: String) {
|
||||||
neLog(type, title: "OVPN: \(title)", message: message)
|
neLog(type, title: "OVPN: \(title)", message: message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func xrayLog(_ type: OSLogType, title: String = "", message: String) {
|
||||||
|
neLog(type, title: "XRAY: \(title)", message: message)
|
||||||
|
}
|
||||||
|
|
||||||
public func neLog(_ type: OSLogType, title: String = "", message: String) {
|
public func neLog(_ type: OSLogType, title: String = "", message: String) {
|
||||||
Log.log(type, title: "NE: \(title)", message: message)
|
Log.log(type, title: "NE: \(title)", message: message)
|
||||||
}
|
}
|
||||||
|
|
159
client/platforms/ios/PacketTunnelProvider+Xray.swift
Normal file
159
client/platforms/ios/PacketTunnelProvider+Xray.swift
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
import Foundation
|
||||||
|
import NetworkExtension
|
||||||
|
import WireGuardKitGo
|
||||||
|
|
||||||
|
enum XrayErrors: Error {
|
||||||
|
case noXrayConfig
|
||||||
|
case cantSaveXrayConfig
|
||||||
|
case cantParseListenAndPort
|
||||||
|
case cantSaveHevSocksConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Constants {
|
||||||
|
static let cachesDirectory: URL = {
|
||||||
|
if let cachesDirectoryURL = FileManager.default.urls(for: .cachesDirectory,
|
||||||
|
in: .userDomainMask).first {
|
||||||
|
return cachesDirectoryURL
|
||||||
|
} else {
|
||||||
|
fatalError("Unable to retrieve caches directory.")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
extension PacketTunnelProvider {
|
||||||
|
func startXray(completionHandler: @escaping (Error?) -> Void) {
|
||||||
|
|
||||||
|
// Xray configuration
|
||||||
|
guard let protocolConfiguration = self.protocolConfiguration as? NETunnelProviderProtocol,
|
||||||
|
let providerConfiguration = protocolConfiguration.providerConfiguration,
|
||||||
|
let xrayConfigData = providerConfiguration[Constants.xrayConfigKey] as? Data else {
|
||||||
|
xrayLog(.error, message: "Can't get xray configuration")
|
||||||
|
completionHandler(XrayErrors.noXrayConfig)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tunnel settings
|
||||||
|
let ipv6Enabled = true
|
||||||
|
let hideVPNIcon = false
|
||||||
|
|
||||||
|
let settings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "254.1.1.1")
|
||||||
|
settings.mtu = 9000
|
||||||
|
|
||||||
|
settings.ipv4Settings = {
|
||||||
|
let settings = NEIPv4Settings(addresses: ["198.18.0.1"], subnetMasks: ["255.255.0.0"])
|
||||||
|
settings.includedRoutes = [NEIPv4Route.default()]
|
||||||
|
return settings
|
||||||
|
}()
|
||||||
|
|
||||||
|
settings.ipv6Settings = {
|
||||||
|
guard ipv6Enabled else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
let settings = NEIPv6Settings(addresses: ["fd6e:a81b:704f:1211::1"], networkPrefixLengths: [64])
|
||||||
|
settings.includedRoutes = [NEIPv6Route.default()]
|
||||||
|
if hideVPNIcon {
|
||||||
|
settings.excludedRoutes = [NEIPv6Route(destinationAddress: "::", networkPrefixLength: 128)]
|
||||||
|
}
|
||||||
|
return settings
|
||||||
|
}()
|
||||||
|
|
||||||
|
let dns = ["8.8.4.4","1.1.1.1"]
|
||||||
|
settings.dnsSettings = NEDNSSettings(servers: dns)
|
||||||
|
|
||||||
|
setTunnelNetworkSettings(settings) { [weak self] error in
|
||||||
|
if let error {
|
||||||
|
completionHandler(error)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Launch xray
|
||||||
|
self?.setupAndStartXray(configData: xrayConfigData) { xrayError in
|
||||||
|
if let xrayError {
|
||||||
|
completionHandler(xrayError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Launch hevSocks
|
||||||
|
self?.setupAndRunTun2socks(configData: xrayConfigData,
|
||||||
|
completionHandler: completionHandler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func stopXray(completionHandler: () -> Void) {
|
||||||
|
Socks5Tunnel.quit()
|
||||||
|
LibXrayStopXray()
|
||||||
|
completionHandler()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setupAndStartXray(configData: Data,
|
||||||
|
completionHandler: @escaping (Error?) -> Void) {
|
||||||
|
let path = Constants.cachesDirectory.appendingPathComponent("config.json", isDirectory: false).path
|
||||||
|
guard FileManager.default.createFile(atPath: path, contents: configData) else {
|
||||||
|
xrayLog(.error, message: "Can't save xray configuration")
|
||||||
|
completionHandler(XrayErrors.cantSaveXrayConfig)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
LibXrayRunXray(nil,
|
||||||
|
path,
|
||||||
|
Int64.max)
|
||||||
|
|
||||||
|
completionHandler(nil)
|
||||||
|
xrayLog(.info, message: "Xray started")
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setupAndRunTun2socks(configData: Data,
|
||||||
|
completionHandler: @escaping (Error?) -> Void) {
|
||||||
|
var port = 10808
|
||||||
|
var address = "::1"
|
||||||
|
|
||||||
|
let jsonDict = try? JSONSerialization.jsonObject(with: configData, options: []) as? [String: Any]
|
||||||
|
|
||||||
|
guard let jsonDict else {
|
||||||
|
xrayLog(.error, message: "Can't parse address and port for hevSocks")
|
||||||
|
completionHandler(XrayErrors.cantParseListenAndPort)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Xray listen and port should be the same as port and address in hevSocks
|
||||||
|
if let inbounds = jsonDict["inbounds"] as? [[String: Any]], let inbound = inbounds.first {
|
||||||
|
if let listen = inbound["listen"] as? String {
|
||||||
|
address = listen
|
||||||
|
address.removeAll { $0 == "[" || $0 == "]" }
|
||||||
|
}
|
||||||
|
if let portFromConfig = inbound["port"] as? Int {
|
||||||
|
port = portFromConfig
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let config = """
|
||||||
|
tunnel:
|
||||||
|
mtu: 9000
|
||||||
|
socks5:
|
||||||
|
port: \(port)
|
||||||
|
address: \(address)
|
||||||
|
udp: 'udp'
|
||||||
|
misc:
|
||||||
|
task-stack-size: 20480
|
||||||
|
connect-timeout: 5000
|
||||||
|
read-write-timeout: 60000
|
||||||
|
log-file: stderr
|
||||||
|
log-level: error
|
||||||
|
limit-nofile: 65535
|
||||||
|
"""
|
||||||
|
|
||||||
|
let configurationFilePath = Constants.cachesDirectory.appendingPathComponent("config.yml", isDirectory: false).path
|
||||||
|
guard FileManager.default.createFile(atPath: configurationFilePath, contents: config.data(using: .utf8)!) else {
|
||||||
|
xrayLog(.info, message: "Cant save hevSocks configuration")
|
||||||
|
completionHandler(XrayErrors.cantSaveHevSocksConfig)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
DispatchQueue.global().async {
|
||||||
|
xrayLog(.info, message: "Hev socks started")
|
||||||
|
completionHandler(nil)
|
||||||
|
Socks5Tunnel.run(withConfig: configurationFilePath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,8 @@ import Darwin
|
||||||
import OpenVPNAdapter
|
import OpenVPNAdapter
|
||||||
|
|
||||||
enum TunnelProtoType: String {
|
enum TunnelProtoType: String {
|
||||||
case wireguard, openvpn
|
case wireguard, openvpn, xray
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Constants {
|
struct Constants {
|
||||||
|
@ -13,6 +14,7 @@ struct Constants {
|
||||||
static let processQueueName = "org.amnezia.process-packets"
|
static let processQueueName = "org.amnezia.process-packets"
|
||||||
static let kActivationAttemptId = "activationAttemptId"
|
static let kActivationAttemptId = "activationAttemptId"
|
||||||
static let ovpnConfigKey = "ovpn"
|
static let ovpnConfigKey = "ovpn"
|
||||||
|
static let xrayConfigKey = "xray"
|
||||||
static let wireGuardConfigKey = "wireguard"
|
static let wireGuardConfigKey = "wireguard"
|
||||||
static let loggerTag = "NET"
|
static let loggerTag = "NET"
|
||||||
|
|
||||||
|
@ -91,6 +93,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||||
protoType = .openvpn
|
protoType = .openvpn
|
||||||
} else if (providerConfiguration?[Constants.wireGuardConfigKey] as? Data) != nil {
|
} else if (providerConfiguration?[Constants.wireGuardConfigKey] as? Data) != nil {
|
||||||
protoType = .wireguard
|
protoType = .wireguard
|
||||||
|
} else if (providerConfiguration?[Constants.xrayConfigKey] as? Data) != nil {
|
||||||
|
protoType = .xray
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,6 +111,9 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||||
completionHandler: completionHandler)
|
completionHandler: completionHandler)
|
||||||
case .openvpn:
|
case .openvpn:
|
||||||
startOpenVPN(completionHandler: completionHandler)
|
startOpenVPN(completionHandler: completionHandler)
|
||||||
|
case .xray:
|
||||||
|
startXray(completionHandler: completionHandler)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,6 +131,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||||
case .openvpn:
|
case .openvpn:
|
||||||
stopOpenVPN(with: reason,
|
stopOpenVPN(with: reason,
|
||||||
completionHandler: completionHandler)
|
completionHandler: completionHandler)
|
||||||
|
case .xray:
|
||||||
|
stopXray(completionHandler: completionHandler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,6 +147,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||||
handleWireguardStatusMessage(messageData, completionHandler: completionHandler)
|
handleWireguardStatusMessage(messageData, completionHandler: completionHandler)
|
||||||
case .openvpn:
|
case .openvpn:
|
||||||
handleOpenVPNStatusMessage(messageData, completionHandler: completionHandler)
|
handleOpenVPNStatusMessage(messageData, completionHandler: completionHandler)
|
||||||
|
case .xray:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,9 +72,11 @@ private:
|
||||||
bool setupCloak();
|
bool setupCloak();
|
||||||
bool setupWireGuard();
|
bool setupWireGuard();
|
||||||
bool setupAwg();
|
bool setupAwg();
|
||||||
|
bool setupXray();
|
||||||
|
|
||||||
bool startOpenVPN(const QString &config);
|
bool startOpenVPN(const QString &config);
|
||||||
bool startWireGuard(const QString &jsonConfig);
|
bool startWireGuard(const QString &jsonConfig);
|
||||||
|
bool startXray(const QString &jsonConfig);
|
||||||
|
|
||||||
void startTunnel();
|
void startTunnel();
|
||||||
|
|
||||||
|
|
|
@ -216,6 +216,9 @@ bool IosController::connectVpn(amnezia::Proto proto, const QJsonObject& configur
|
||||||
if (proto == amnezia::Proto::Awg) {
|
if (proto == amnezia::Proto::Awg) {
|
||||||
return setupAwg();
|
return setupAwg();
|
||||||
}
|
}
|
||||||
|
if (proto == amnezia::Proto::Xray) {
|
||||||
|
return setupXray();
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -501,6 +504,15 @@ bool IosController::setupWireGuard()
|
||||||
return startWireGuard(wgConfigDocStr);
|
return startWireGuard(wgConfigDocStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IosController::setupXray()
|
||||||
|
{
|
||||||
|
QJsonObject config = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::Xray)].toObject();
|
||||||
|
QJsonDocument xrayConfigDoc(config);
|
||||||
|
QString xrayConfigStr(xrayConfigDoc.toJson(QJsonDocument::Compact));
|
||||||
|
|
||||||
|
return startXray(xrayConfigStr);
|
||||||
|
}
|
||||||
|
|
||||||
bool IosController::setupAwg()
|
bool IosController::setupAwg()
|
||||||
{
|
{
|
||||||
QJsonObject config = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::Awg)].toObject();
|
QJsonObject config = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::Awg)].toObject();
|
||||||
|
@ -590,6 +602,20 @@ bool IosController::startWireGuard(const QString &config)
|
||||||
startTunnel();
|
startTunnel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IosController::startXray(const QString &config)
|
||||||
|
{
|
||||||
|
qDebug() << "IosController::startXray";
|
||||||
|
|
||||||
|
NETunnelProviderProtocol *tunnelProtocol = [[NETunnelProviderProtocol alloc] init];
|
||||||
|
tunnelProtocol.providerBundleIdentifier = [NSString stringWithUTF8String:VPN_NE_BUNDLEID];
|
||||||
|
tunnelProtocol.providerConfiguration = @{@"xray": [[NSString stringWithUTF8String:config.toStdString().c_str()] dataUsingEncoding:NSUTF8StringEncoding]};
|
||||||
|
tunnelProtocol.serverAddress = m_serverAddress;
|
||||||
|
|
||||||
|
m_currentTunnel.protocolConfiguration = tunnelProtocol;
|
||||||
|
|
||||||
|
startTunnel();
|
||||||
|
}
|
||||||
|
|
||||||
void IosController::startTunnel()
|
void IosController::startTunnel()
|
||||||
{
|
{
|
||||||
NSString *protocolName = @"Unknown";
|
NSString *protocolName = @"Unknown";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue