mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-06-23 02:00:20 +07:00
Setup MTU for iOS
This commit is contained in:
@@ -38,7 +38,7 @@ struct Log {
|
|||||||
init(_ str: String) {
|
init(_ str: String) {
|
||||||
self.records = str.split(whereSeparator: \.isNewline)
|
self.records = str.split(whereSeparator: \.isNewline)
|
||||||
.compactMap {
|
.compactMap {
|
||||||
Record(String($0))!
|
Record(String($0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,40 +18,32 @@ extension PacketTunnelProvider: OpenVPNAdapterDelegate {
|
|||||||
// send empty string to NEDNSSettings.matchDomains
|
// send empty string to NEDNSSettings.matchDomains
|
||||||
networkSettings?.dnsSettings?.matchDomains = [""]
|
networkSettings?.dnsSettings?.matchDomains = [""]
|
||||||
|
|
||||||
if splitTunnelType == "1" {
|
if splitTunnelType == 1 {
|
||||||
var ipv4IncludedRoutes = [NEIPv4Route]()
|
var ipv4IncludedRoutes = [NEIPv4Route]()
|
||||||
let STSdata = Data(splitTunnelSites!.utf8)
|
|
||||||
do {
|
for allowedIPString in splitTunnelSites {
|
||||||
guard let STSArray = try JSONSerialization.jsonObject(with: STSdata) as? [String] else { return }
|
if let allowedIP = IPAddressRange(from: allowedIPString) {
|
||||||
for allowedIPString in STSArray {
|
ipv4IncludedRoutes.append(NEIPv4Route(
|
||||||
if let allowedIP = IPAddressRange(from: allowedIPString) {
|
destinationAddress: "\(allowedIP.address)",
|
||||||
ipv4IncludedRoutes.append(NEIPv4Route(
|
subnetMask: "\(allowedIP.subnetMask())"))
|
||||||
destinationAddress: "\(allowedIP.address)",
|
|
||||||
subnetMask: "\(allowedIP.subnetMask())"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch {
|
|
||||||
wg_log(.error, message: "Parse JSONSerialization Error")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
networkSettings?.ipv4Settings?.includedRoutes = ipv4IncludedRoutes
|
networkSettings?.ipv4Settings?.includedRoutes = ipv4IncludedRoutes
|
||||||
} else {
|
} else {
|
||||||
if splitTunnelType == "2" {
|
if splitTunnelType == 2 {
|
||||||
var ipv4ExcludedRoutes = [NEIPv4Route]()
|
var ipv4ExcludedRoutes = [NEIPv4Route]()
|
||||||
var ipv4IncludedRoutes = [NEIPv4Route]()
|
var ipv4IncludedRoutes = [NEIPv4Route]()
|
||||||
var ipv6IncludedRoutes = [NEIPv6Route]()
|
var ipv6IncludedRoutes = [NEIPv6Route]()
|
||||||
let STSdata = Data(splitTunnelSites!.utf8)
|
|
||||||
do {
|
for excludeIPString in splitTunnelSites {
|
||||||
guard let STSArray = try JSONSerialization.jsonObject(with: STSdata) as? [String] else { return }
|
if let excludeIP = IPAddressRange(from: excludeIPString) {
|
||||||
for excludeIPString in STSArray {
|
ipv4ExcludedRoutes.append(NEIPv4Route(
|
||||||
if let excludeIP = IPAddressRange(from: excludeIPString) {
|
destinationAddress: "\(excludeIP.address)",
|
||||||
ipv4ExcludedRoutes.append(NEIPv4Route(
|
subnetMask: "\(excludeIP.subnetMask())"))
|
||||||
destinationAddress: "\(excludeIP.address)",
|
|
||||||
subnetMask: "\(excludeIP.subnetMask())"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch {
|
|
||||||
wg_log(.error, message: "Parse JSONSerialization Error")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let allIPv4 = IPAddressRange(from: "0.0.0.0/0") {
|
if let allIPv4 = IPAddressRange(from: "0.0.0.0/0") {
|
||||||
ipv4IncludedRoutes.append(NEIPv4Route(
|
ipv4IncludedRoutes.append(NEIPv4Route(
|
||||||
destinationAddress: "\(allIPv4.address)",
|
destinationAddress: "\(allIPv4.address)",
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
|||||||
private let dispatchQueue = DispatchQueue(label: "PacketTunnel", qos: .utility)
|
private let dispatchQueue = DispatchQueue(label: "PacketTunnel", qos: .utility)
|
||||||
|
|
||||||
private var openVPNConfig: Data?
|
private var openVPNConfig: Data?
|
||||||
var splitTunnelType: String?
|
var splitTunnelType: Int!
|
||||||
var splitTunnelSites: String?
|
var splitTunnelSites: [String]!
|
||||||
|
|
||||||
let vpnReachability = OpenVPNReachability()
|
let vpnReachability = OpenVPNReachability()
|
||||||
|
|
||||||
@@ -83,8 +83,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if action == Constants.kActionStart {
|
if action == Constants.kActionStart {
|
||||||
splitTunnelType = message[Constants.kMessageKeySplitTunnelType] as? String
|
// splitTunnelType = message[Constants.kMessageKeySplitTunnelType] as? String
|
||||||
splitTunnelSites = message[Constants.kMessageKeySplitTunnelSites] as? String
|
// splitTunnelSites = message[Constants.kMessageKeySplitTunnelSites] as? String
|
||||||
}
|
}
|
||||||
|
|
||||||
let callbackWrapper: (NSNumber?) -> Void = { errorCode in
|
let callbackWrapper: (NSNumber?) -> Void = { errorCode in
|
||||||
@@ -169,110 +169,118 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
|||||||
completionHandler: @escaping (Error?) -> Void) {
|
completionHandler: @escaping (Error?) -> Void) {
|
||||||
guard let protocolConfiguration = self.protocolConfiguration as? NETunnelProviderProtocol,
|
guard let protocolConfiguration = self.protocolConfiguration as? NETunnelProviderProtocol,
|
||||||
let providerConfiguration = protocolConfiguration.providerConfiguration,
|
let providerConfiguration = protocolConfiguration.providerConfiguration,
|
||||||
let wgConfig: Data = providerConfiguration[Constants.wireGuardConfigKey] as? Data else {
|
let wgConfigData: Data = providerConfiguration[Constants.wireGuardConfigKey] as? Data else {
|
||||||
wg_log(.error, message: "Can't start WireGuard config missing")
|
wg_log(.error, message: "Can't start WireGuard config missing")
|
||||||
completionHandler(nil)
|
completionHandler(nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let wgConfigStr = try? JSONDecoder().decode(WGConfig.self, from: wgConfig).wg,
|
do {
|
||||||
let tunnelConfiguration = try? TunnelConfiguration(fromWgQuickConfig: wgConfigStr)
|
let wgConfig = try JSONDecoder().decode(WGConfig.self, from: wgConfigData)
|
||||||
else {
|
let wgConfigStr = wgConfig.str
|
||||||
wg_log(.error, message: "Can't parse WireGuard config")
|
log(.info, message: "wgConfig: \(wgConfig.redux.replacingOccurrences(of: "\n", with: " "))")
|
||||||
completionHandler(nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
log(.info, message: "wgConfig: \(wgConfigStr.replacingOccurrences(of: "\n", with: " "))")
|
let tunnelConfiguration = try TunnelConfiguration(fromWgQuickConfig: wgConfigStr)
|
||||||
|
|
||||||
if tunnelConfiguration.peers.first!.allowedIPs
|
if tunnelConfiguration.peers.first!.allowedIPs
|
||||||
.map({ $0.stringRepresentation })
|
.map({ $0.stringRepresentation })
|
||||||
.joined(separator: ", ") == "0.0.0.0/0, ::/0" {
|
.joined(separator: ", ") == "0.0.0.0/0, ::/0" {
|
||||||
if splitTunnelType == "1" {
|
if wgConfig.splitTunnelType == 1 {
|
||||||
for index in tunnelConfiguration.peers.indices {
|
for index in tunnelConfiguration.peers.indices {
|
||||||
tunnelConfiguration.peers[index].allowedIPs.removeAll()
|
tunnelConfiguration.peers[index].allowedIPs.removeAll()
|
||||||
var allowedIPs = [IPAddressRange]()
|
var allowedIPs = [IPAddressRange]()
|
||||||
let STSdata = Data(splitTunnelSites!.utf8)
|
|
||||||
do {
|
for allowedIPString in wgConfig.splitTunnelSites {
|
||||||
guard let STSArray = try JSONSerialization.jsonObject(with: STSdata) as? [String] else { return }
|
|
||||||
for allowedIPString in STSArray {
|
|
||||||
if let allowedIP = IPAddressRange(from: allowedIPString) {
|
if let allowedIP = IPAddressRange(from: allowedIPString) {
|
||||||
allowedIPs.append(allowedIP)
|
allowedIPs.append(allowedIP)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch {
|
|
||||||
wg_log(.error, message: "Parse JSONSerialization Error")
|
tunnelConfiguration.peers[index].allowedIPs = allowedIPs
|
||||||
}
|
}
|
||||||
tunnelConfiguration.peers[index].allowedIPs = allowedIPs
|
} else if wgConfig.splitTunnelType == 2 {
|
||||||
}
|
for index in tunnelConfiguration.peers.indices {
|
||||||
} else if splitTunnelType == "2" {
|
var excludeIPs = [IPAddressRange]()
|
||||||
for index in tunnelConfiguration.peers.indices {
|
|
||||||
var excludeIPs = [IPAddressRange]()
|
for excludeIPString in wgConfig.splitTunnelSites {
|
||||||
let STSdata = Data(splitTunnelSites!.utf8)
|
|
||||||
do {
|
|
||||||
guard let STSArray = try JSONSerialization.jsonObject(with: STSdata) as? [String] else { return }
|
|
||||||
for excludeIPString in STSArray {
|
|
||||||
if let excludeIP = IPAddressRange(from: excludeIPString) {
|
if let excludeIP = IPAddressRange(from: excludeIPString) {
|
||||||
excludeIPs.append(excludeIP)
|
excludeIPs.append(excludeIP)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch {
|
|
||||||
wg_log(.error, message: "Parse JSONSerialization Error")
|
tunnelConfiguration.peers[index].excludeIPs = excludeIPs
|
||||||
}
|
}
|
||||||
tunnelConfiguration.peers[index].excludeIPs = excludeIPs
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
wg_log(.info, message: "Starting wireguard tunnel from the " +
|
wg_log(.info, message: "Starting wireguard tunnel from the " +
|
||||||
(activationAttemptId == nil ? "OS directly, rather than the app" : "app"))
|
(activationAttemptId == nil ? "OS directly, rather than the app" : "app"))
|
||||||
|
|
||||||
// Start the tunnel
|
// Start the tunnel
|
||||||
wgAdapter.start(tunnelConfiguration: tunnelConfiguration) { adapterError in
|
wgAdapter.start(tunnelConfiguration: tunnelConfiguration) { adapterError in
|
||||||
guard let adapterError else {
|
guard let adapterError else {
|
||||||
let interfaceName = self.wgAdapter.interfaceName ?? "unknown"
|
let interfaceName = self.wgAdapter.interfaceName ?? "unknown"
|
||||||
wg_log(.info, message: "Tunnel interface is \(interfaceName)")
|
wg_log(.info, message: "Tunnel interface is \(interfaceName)")
|
||||||
completionHandler(nil)
|
completionHandler(nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch adapterError {
|
switch adapterError {
|
||||||
case .cannotLocateTunnelFileDescriptor:
|
case .cannotLocateTunnelFileDescriptor:
|
||||||
wg_log(.error, staticMessage: "Starting tunnel failed: could not determine file descriptor")
|
wg_log(.error, staticMessage: "Starting tunnel failed: could not determine file descriptor")
|
||||||
errorNotifier.notify(PacketTunnelProviderError.couldNotDetermineFileDescriptor)
|
errorNotifier.notify(PacketTunnelProviderError.couldNotDetermineFileDescriptor)
|
||||||
completionHandler(PacketTunnelProviderError.couldNotDetermineFileDescriptor)
|
completionHandler(PacketTunnelProviderError.couldNotDetermineFileDescriptor)
|
||||||
case .dnsResolution(let dnsErrors):
|
case .dnsResolution(let dnsErrors):
|
||||||
let hostnamesWithDnsResolutionFailure = dnsErrors.map { $0.address }
|
let hostnamesWithDnsResolutionFailure = dnsErrors.map { $0.address }
|
||||||
.joined(separator: ", ")
|
.joined(separator: ", ")
|
||||||
wg_log(.error, message:
|
wg_log(.error, message:
|
||||||
"DNS resolution failed for the following hostnames: \(hostnamesWithDnsResolutionFailure)")
|
"DNS resolution failed for the following hostnames: \(hostnamesWithDnsResolutionFailure)")
|
||||||
errorNotifier.notify(PacketTunnelProviderError.dnsResolutionFailure)
|
errorNotifier.notify(PacketTunnelProviderError.dnsResolutionFailure)
|
||||||
completionHandler(PacketTunnelProviderError.dnsResolutionFailure)
|
completionHandler(PacketTunnelProviderError.dnsResolutionFailure)
|
||||||
case .setNetworkSettings(let error):
|
case .setNetworkSettings(let error):
|
||||||
wg_log(.error, message:
|
wg_log(.error, message:
|
||||||
"Starting tunnel failed with setTunnelNetworkSettings returning \(error.localizedDescription)")
|
"Starting tunnel failed with setTunnelNetworkSettings returning \(error.localizedDescription)")
|
||||||
errorNotifier.notify(PacketTunnelProviderError.couldNotSetNetworkSettings)
|
errorNotifier.notify(PacketTunnelProviderError.couldNotSetNetworkSettings)
|
||||||
completionHandler(PacketTunnelProviderError.couldNotSetNetworkSettings)
|
completionHandler(PacketTunnelProviderError.couldNotSetNetworkSettings)
|
||||||
case .startWireGuardBackend(let errorCode):
|
case .startWireGuardBackend(let errorCode):
|
||||||
wg_log(.error, message: "Starting tunnel failed with wgTurnOn returning \(errorCode)")
|
wg_log(.error, message: "Starting tunnel failed with wgTurnOn returning \(errorCode)")
|
||||||
errorNotifier.notify(PacketTunnelProviderError.couldNotStartBackend)
|
errorNotifier.notify(PacketTunnelProviderError.couldNotStartBackend)
|
||||||
completionHandler(PacketTunnelProviderError.couldNotStartBackend)
|
completionHandler(PacketTunnelProviderError.couldNotStartBackend)
|
||||||
case .invalidState:
|
case .invalidState:
|
||||||
fatalError()
|
fatalError()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch {
|
||||||
|
log(.error, message: "Can't parse WG config: \(error.localizedDescription)")
|
||||||
|
completionHandler(nil)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func startOpenVPN(completionHandler: @escaping (Error?) -> Void) {
|
private func startOpenVPN(completionHandler: @escaping (Error?) -> Void) {
|
||||||
guard let protocolConfiguration = self.protocolConfiguration as? NETunnelProviderProtocol,
|
guard let protocolConfiguration = self.protocolConfiguration as? NETunnelProviderProtocol,
|
||||||
let providerConfiguration = protocolConfiguration.providerConfiguration,
|
let providerConfiguration = protocolConfiguration.providerConfiguration,
|
||||||
let ovpnConfiguration: Data = providerConfiguration[Constants.ovpnConfigKey] as? Data else {
|
let openVPNConfigData = providerConfiguration[Constants.ovpnConfigKey] as? Data else {
|
||||||
|
|
||||||
wg_log(.error, message: "Can't start startOpenVPN()")
|
wg_log(.error, message: "Can't start startOpenVPN()")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
setupAndlaunchOpenVPN(withConfig: ovpnConfiguration, completionHandler: completionHandler)
|
do {
|
||||||
|
log(.info, message: "providerConfiguration: \(String(decoding: openVPNConfigData, as: UTF8.self).replacingOccurrences(of: "\n", with: " "))")
|
||||||
|
|
||||||
|
let openVPNConfig = try JSONDecoder().decode(OpenVPNConfig.self, from: openVPNConfigData)
|
||||||
|
log(.info, message: "openVPNConfig: \(openVPNConfig.str.replacingOccurrences(of: "\n", with: " "))")
|
||||||
|
let ovpnConfiguration = Data(openVPNConfig.config.utf8)
|
||||||
|
setupAndlaunchOpenVPN(withConfig: ovpnConfiguration, completionHandler: completionHandler)
|
||||||
|
} catch {
|
||||||
|
log(.error, message: "Can't parse OpenVPN config: \(error.localizedDescription)")
|
||||||
|
|
||||||
|
if let underlyingError = (error as NSError).userInfo[NSUnderlyingErrorKey] as? NSError {
|
||||||
|
log(.error, message: "Can't parse OpenVPN config: \(underlyingError.localizedDescription)")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func stopWireguard(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
|
private func stopWireguard(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
|
||||||
|
|||||||
@@ -1,9 +1,41 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct WGConfigData: Decodable {
|
struct WGConfig: Decodable {
|
||||||
let h1, h2, h3, h4: String?
|
let h1, h2, h3, h4: String?
|
||||||
let jc, jmax, jmin: String?
|
let jc, jmax, jmin: String?
|
||||||
let s1, s2: String?
|
let s1, s2: String?
|
||||||
|
let dns1: String
|
||||||
|
let dns2: String
|
||||||
|
let mtu: String
|
||||||
|
let hostName: String
|
||||||
|
let port: Int
|
||||||
|
let clientIP: String
|
||||||
|
let clientPrivateKey: String
|
||||||
|
let serverPublicKey: String
|
||||||
|
let presharedKey: String
|
||||||
|
var allowedIPs: [String]
|
||||||
|
var persistentKeepAlive: String
|
||||||
|
let splitTunnelType: Int
|
||||||
|
let splitTunnelSites: [String]
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case h1 = "H1", h2 = "H2", h3 = "H3", h4 = "H4"
|
||||||
|
case jc = "Jc", jmax = "Jmax", jmin = "Jmin"
|
||||||
|
case s1 = "S1", s2 = "S2"
|
||||||
|
case dns1
|
||||||
|
case dns2
|
||||||
|
case mtu
|
||||||
|
case hostName
|
||||||
|
case port
|
||||||
|
case clientIP = "client_ip"
|
||||||
|
case clientPrivateKey = "client_priv_key"
|
||||||
|
case serverPublicKey = "server_pub_key"
|
||||||
|
case presharedKey = "psk_key"
|
||||||
|
case allowedIPs = "allowed_ips"
|
||||||
|
case persistentKeepAlive = "persistent_keep_alive"
|
||||||
|
case splitTunnelType
|
||||||
|
case splitTunnelSites
|
||||||
|
}
|
||||||
|
|
||||||
var settings: String {
|
var settings: String {
|
||||||
jc == nil ? "" :
|
jc == nil ? "" :
|
||||||
@@ -21,113 +53,48 @@ struct WGConfigData: Decodable {
|
|||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
|
|
||||||
let clientIP: String
|
var str: String {
|
||||||
let clientPrivateKey: String
|
|
||||||
let clientPublicKey: String
|
|
||||||
let serverPublicKey: String
|
|
||||||
let presharedKey: String
|
|
||||||
let hostName: String
|
|
||||||
let port: Int
|
|
||||||
|
|
||||||
var allowedIPs: [String]
|
|
||||||
var persistentKeepAlive: String
|
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
|
||||||
case h1 = "H1", h2 = "H2", h3 = "H3", h4 = "H4"
|
|
||||||
case jc = "Jc", jmax = "Jmax", jmin = "Jmin"
|
|
||||||
case s1 = "S1", s2 = "S2"
|
|
||||||
|
|
||||||
case clientIP = "client_ip" // "10.8.1.16"
|
|
||||||
case clientPrivateKey = "client_priv_key"
|
|
||||||
case clientPublicKey = "client_pub_key"
|
|
||||||
case serverPublicKey = "server_pub_key"
|
|
||||||
case presharedKey = "psk_key"
|
|
||||||
|
|
||||||
case allowedIPs = "allowed_ips"
|
|
||||||
case persistentKeepAlive = "persistent_keep_alive"
|
|
||||||
case hostName
|
|
||||||
case port
|
|
||||||
}
|
|
||||||
|
|
||||||
init(from decoder: Decoder) throws {
|
|
||||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
||||||
self.h1 = try container.decodeIfPresent(String.self, forKey: .h1)
|
|
||||||
self.h2 = try container.decodeIfPresent(String.self, forKey: .h2)
|
|
||||||
self.h3 = try container.decodeIfPresent(String.self, forKey: .h3)
|
|
||||||
self.h4 = try container.decodeIfPresent(String.self, forKey: .h4)
|
|
||||||
self.jc = try container.decodeIfPresent(String.self, forKey: .jc)
|
|
||||||
self.jmax = try container.decodeIfPresent(String.self, forKey: .jmax)
|
|
||||||
self.jmin = try container.decodeIfPresent(String.self, forKey: .jmin)
|
|
||||||
self.s1 = try container.decodeIfPresent(String.self, forKey: .s1)
|
|
||||||
self.s2 = try container.decodeIfPresent(String.self, forKey: .s2)
|
|
||||||
self.clientIP = try container.decode(String.self, forKey: .clientIP)
|
|
||||||
self.clientPrivateKey = try container.decode(String.self, forKey: .clientPrivateKey)
|
|
||||||
self.clientPublicKey = try container.decode(String.self, forKey: .clientPublicKey)
|
|
||||||
self.serverPublicKey = try container.decode(String.self, forKey: .serverPublicKey)
|
|
||||||
self.presharedKey = try container.decode(String.self, forKey: .presharedKey)
|
|
||||||
self.allowedIPs = try container.decodeIfPresent([String].self, forKey: .allowedIPs) ?? ["0.0.0.0/0", "::/0"]
|
|
||||||
self.persistentKeepAlive = try container.decodeIfPresent(String.self, forKey: .persistentKeepAlive) ?? "25"
|
|
||||||
self.hostName = try container.decode(String.self, forKey: .hostName)
|
|
||||||
self.port = try container.decode(Int.self, forKey: .port)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct WGConfig: Decodable {
|
|
||||||
let data: WGConfigData
|
|
||||||
let configVersion: Int
|
|
||||||
let description: String
|
|
||||||
let dns1: String
|
|
||||||
let dns2: String
|
|
||||||
let hostName: String
|
|
||||||
let `protocol`: String
|
|
||||||
let splitTunnelSites: [String]
|
|
||||||
let splitTunnelType: Int
|
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
|
||||||
case awgConfigData = "awg_config_data", wgConfigData = "wireguard_config_data"
|
|
||||||
case configData
|
|
||||||
case configVersion = "config_version"
|
|
||||||
case description
|
|
||||||
case dns1
|
|
||||||
case dns2
|
|
||||||
case hostName
|
|
||||||
case `protocol`
|
|
||||||
case splitTunnelSites
|
|
||||||
case splitTunnelType
|
|
||||||
}
|
|
||||||
|
|
||||||
init(from decoder: Decoder) throws {
|
|
||||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
||||||
|
|
||||||
if container.contains(.awgConfigData) {
|
|
||||||
self.data = try container.decode(WGConfigData.self, forKey: .awgConfigData)
|
|
||||||
} else {
|
|
||||||
self.data = try container.decode(WGConfigData.self, forKey: .wgConfigData)
|
|
||||||
}
|
|
||||||
|
|
||||||
self.configVersion = try container.decode(Int.self, forKey: .configVersion)
|
|
||||||
self.description = try container.decode(String.self, forKey: .description)
|
|
||||||
self.dns1 = try container.decode(String.self, forKey: .dns1)
|
|
||||||
self.dns2 = try container.decode(String.self, forKey: .dns2)
|
|
||||||
self.hostName = try container.decode(String.self, forKey: .hostName)
|
|
||||||
self.protocol = try container.decode(String.self, forKey: .protocol)
|
|
||||||
self.splitTunnelSites = try container.decode([String].self, forKey: .splitTunnelSites)
|
|
||||||
self.splitTunnelType = try container.decode(Int.self, forKey: .splitTunnelType)
|
|
||||||
}
|
|
||||||
|
|
||||||
var wg: String {
|
|
||||||
"""
|
"""
|
||||||
[Interface]
|
[Interface]
|
||||||
Address = \(data.clientIP)/32
|
Address = \(clientIP)/32
|
||||||
DNS = \(dns1), \(dns2)
|
DNS = \(dns1), \(dns2)
|
||||||
PrivateKey = \(data.clientPrivateKey)
|
MTU = \(mtu)
|
||||||
\(data.settings)
|
PrivateKey = \(clientPrivateKey)
|
||||||
|
\(settings)
|
||||||
[Peer]
|
[Peer]
|
||||||
PublicKey = \(data.serverPublicKey)
|
PublicKey = \(serverPublicKey)
|
||||||
PresharedKey = \(data.presharedKey)
|
PresharedKey = \(presharedKey)
|
||||||
AllowedIPs = \(data.allowedIPs.joined(separator: ", "))
|
AllowedIPs = \(allowedIPs.joined(separator: ", "))
|
||||||
Endpoint = \(data.hostName):\(data.port)
|
Endpoint = \(hostName):\(port)
|
||||||
PersistentKeepalive = \(data.persistentKeepAlive)
|
PersistentKeepalive = \(persistentKeepAlive)
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
var redux: String {
|
||||||
|
"""
|
||||||
|
[Interface]
|
||||||
|
Address = \(clientIP)/32
|
||||||
|
DNS = \(dns1), \(dns2)
|
||||||
|
MTU = \(mtu)
|
||||||
|
PrivateKey = ***
|
||||||
|
\(settings)
|
||||||
|
[Peer]
|
||||||
|
PublicKey = ***
|
||||||
|
PresharedKey = ***
|
||||||
|
AllowedIPs = \(allowedIPs.joined(separator: ", "))
|
||||||
|
Endpoint = \(hostName):\(port)
|
||||||
|
PersistentKeepalive = \(persistentKeepAlive)
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct OpenVPNConfig: Decodable {
|
||||||
|
let config: String
|
||||||
|
let mtu: String
|
||||||
|
let splitTunnelType: Int
|
||||||
|
let splitTunnelSites: [String]
|
||||||
|
|
||||||
|
var str: String {
|
||||||
|
"splitTunnelType: \(splitTunnelType) splitTunnelSites: \(splitTunnelSites) mtu: \(mtu) config: \(config)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -357,7 +357,16 @@ bool IosController::setupOpenVPN()
|
|||||||
QJsonObject ovpn = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::OpenVpn)].toObject();
|
QJsonObject ovpn = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::OpenVpn)].toObject();
|
||||||
QString ovpnConfig = ovpn[config_key::config].toString();
|
QString ovpnConfig = ovpn[config_key::config].toString();
|
||||||
|
|
||||||
return startOpenVPN(ovpnConfig);
|
QJsonObject openVPNConfig {};
|
||||||
|
openVPNConfig.insert(config_key::config, ovpnConfig);
|
||||||
|
openVPNConfig.insert(config_key::mtu, m_rawConfig[config_key::mtu]);
|
||||||
|
openVPNConfig.insert(config_key::splitTunnelType, m_rawConfig[config_key::splitTunnelType]);
|
||||||
|
openVPNConfig.insert(config_key::splitTunnelSites, m_rawConfig[config_key::splitTunnelSites]);
|
||||||
|
|
||||||
|
QJsonDocument openVPNConfigDoc(openVPNConfig);
|
||||||
|
QString openVPNConfigStr(openVPNConfigDoc.toJson(QJsonDocument::Compact));
|
||||||
|
|
||||||
|
return startOpenVPN(openVPNConfigStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IosController::setupCloak()
|
bool IosController::setupCloak()
|
||||||
@@ -394,27 +403,100 @@ bool IosController::setupCloak()
|
|||||||
ovpnConfig.append(cloakBase64);
|
ovpnConfig.append(cloakBase64);
|
||||||
ovpnConfig.append("\n</cloak>\n");
|
ovpnConfig.append("\n</cloak>\n");
|
||||||
|
|
||||||
return startOpenVPN(ovpnConfig);
|
QJsonObject openVPNConfig {};
|
||||||
|
openVPNConfig.insert(config_key::config, ovpnConfig);
|
||||||
|
openVPNConfig.insert(config_key::mtu, m_rawConfig[config_key::mtu]);
|
||||||
|
openVPNConfig.insert(config_key::splitTunnelType, m_rawConfig[config_key::splitTunnelType]);
|
||||||
|
openVPNConfig.insert(config_key::splitTunnelSites, m_rawConfig[config_key::splitTunnelSites]);
|
||||||
|
|
||||||
|
QJsonDocument openVPNConfigDoc(openVPNConfig);
|
||||||
|
QString openVPNConfigStr(openVPNConfigDoc.toJson(QJsonDocument::Compact));
|
||||||
|
|
||||||
|
return startOpenVPN(openVPNConfigStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IosController::setupWireGuard()
|
bool IosController::setupWireGuard()
|
||||||
{
|
{
|
||||||
QJsonObject config = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::WireGuard)].toObject();
|
QJsonObject config = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::WireGuard)].toObject();
|
||||||
|
|
||||||
QJsonDocument doc(m_rawConfig);
|
QJsonObject wgConfig {};
|
||||||
QString wgConfig(doc.toJson(QJsonDocument::Compact));
|
wgConfig.insert(config_key::dns1, m_rawConfig[config_key::dns1]);
|
||||||
|
wgConfig.insert(config_key::dns2, m_rawConfig[config_key::dns2]);
|
||||||
|
wgConfig.insert(config_key::mtu, config[config_key::mtu]);
|
||||||
|
wgConfig.insert(config_key::hostName, config[config_key::hostName]);
|
||||||
|
wgConfig.insert(config_key::port, config[config_key::port]);
|
||||||
|
wgConfig.insert(config_key::client_ip, config[config_key::client_ip]);
|
||||||
|
wgConfig.insert(config_key::client_priv_key, config[config_key::client_priv_key]);
|
||||||
|
wgConfig.insert(config_key::server_pub_key, config[config_key::server_pub_key]);
|
||||||
|
wgConfig.insert(config_key::psk_key, config[config_key::psk_key]);
|
||||||
|
wgConfig.insert(config_key::splitTunnelType, m_rawConfig[config_key::splitTunnelType]);
|
||||||
|
wgConfig.insert(config_key::splitTunnelSites, m_rawConfig[config_key::splitTunnelSites]);
|
||||||
|
|
||||||
return startWireGuard(wgConfig);
|
if (config.contains(config_key::allowed_ips)) {
|
||||||
|
wgConfig.insert(config_key::allowed_ips, config[config_key::allowed_ips]);
|
||||||
|
} else {
|
||||||
|
QJsonArray allowed_ips { "0.0.0.0/0", "::/0" };
|
||||||
|
wgConfig.insert(config_key::allowed_ips, allowed_ips);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.contains(config_key::persistent_keep_alive)) {
|
||||||
|
wgConfig.insert(config_key::persistent_keep_alive, config[config_key::persistent_keep_alive]);
|
||||||
|
} else {
|
||||||
|
wgConfig.insert(config_key::persistent_keep_alive, "25");
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonDocument wgConfigDoc(wgConfig);
|
||||||
|
QString wgConfigDocStr(wgConfigDoc.toJson(QJsonDocument::Compact));
|
||||||
|
|
||||||
|
return startWireGuard(wgConfigDocStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
|
|
||||||
QJsonDocument doc(m_rawConfig);
|
QJsonObject wgConfig {};
|
||||||
QString wgConfig(doc.toJson(QJsonDocument::Compact));
|
wgConfig.insert(config_key::dns1, m_rawConfig[config_key::dns1]);
|
||||||
|
wgConfig.insert(config_key::dns2, m_rawConfig[config_key::dns2]);
|
||||||
|
wgConfig.insert(config_key::mtu, config[config_key::mtu]);
|
||||||
|
wgConfig.insert(config_key::hostName, config[config_key::hostName]);
|
||||||
|
wgConfig.insert(config_key::port, config[config_key::port]);
|
||||||
|
wgConfig.insert(config_key::client_ip, config[config_key::client_ip]);
|
||||||
|
wgConfig.insert(config_key::client_priv_key, config[config_key::client_priv_key]);
|
||||||
|
wgConfig.insert(config_key::server_pub_key, config[config_key::server_pub_key]);
|
||||||
|
wgConfig.insert(config_key::psk_key, config[config_key::psk_key]);
|
||||||
|
wgConfig.insert(config_key::splitTunnelType, m_rawConfig[config_key::splitTunnelType]);
|
||||||
|
wgConfig.insert(config_key::splitTunnelSites, m_rawConfig[config_key::splitTunnelSites]);
|
||||||
|
|
||||||
return startWireGuard(wgConfig);
|
if (config.contains(config_key::allowed_ips)) {
|
||||||
|
wgConfig.insert(config_key::allowed_ips, config[config_key::allowed_ips]);
|
||||||
|
} else {
|
||||||
|
QJsonArray allowed_ips { "0.0.0.0/0", "::/0" };
|
||||||
|
wgConfig.insert(config_key::allowed_ips, allowed_ips);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.contains(config_key::persistent_keep_alive)) {
|
||||||
|
wgConfig.insert(config_key::persistent_keep_alive, config[config_key::persistent_keep_alive]);
|
||||||
|
} else {
|
||||||
|
wgConfig.insert(config_key::persistent_keep_alive, "25");
|
||||||
|
}
|
||||||
|
|
||||||
|
wgConfig.insert(config_key::initPacketMagicHeader, config[config_key::initPacketMagicHeader]);
|
||||||
|
wgConfig.insert(config_key::responsePacketMagicHeader, config[config_key::responsePacketMagicHeader]);
|
||||||
|
wgConfig.insert(config_key::underloadPacketMagicHeader, config[config_key::underloadPacketMagicHeader]);
|
||||||
|
wgConfig.insert(config_key::transportPacketMagicHeader, config[config_key::transportPacketMagicHeader]);
|
||||||
|
|
||||||
|
wgConfig.insert(config_key::initPacketJunkSize, config[config_key::initPacketJunkSize]);
|
||||||
|
wgConfig.insert(config_key::responsePacketJunkSize, config[config_key::responsePacketJunkSize]);
|
||||||
|
|
||||||
|
wgConfig.insert(config_key::junkPacketCount, config[config_key::junkPacketCount]);
|
||||||
|
wgConfig.insert(config_key::junkPacketMinSize, config[config_key::junkPacketMinSize]);
|
||||||
|
wgConfig.insert(config_key::junkPacketMaxSize, config[config_key::junkPacketMaxSize]);
|
||||||
|
|
||||||
|
QJsonDocument wgConfigDoc(wgConfig);
|
||||||
|
QString wgConfigDocStr(wgConfigDoc.toJson(QJsonDocument::Compact));
|
||||||
|
|
||||||
|
return startWireGuard(wgConfigDocStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IosController::startOpenVPN(const QString &config)
|
bool IosController::startOpenVPN(const QString &config)
|
||||||
@@ -499,7 +581,7 @@ void IosController::startTunnel()
|
|||||||
NSDictionary* message = @{actionKey: actionValue, tunnelIdKey: tunnelIdValue,
|
NSDictionary* message = @{actionKey: actionValue, tunnelIdKey: tunnelIdValue,
|
||||||
SplitTunnelTypeKey: SplitTunnelTypeValue, SplitTunnelSitesKey: SplitTunnelSitesValue};
|
SplitTunnelTypeKey: SplitTunnelTypeValue, SplitTunnelSitesKey: SplitTunnelSitesValue};
|
||||||
|
|
||||||
sendVpnExtensionMessage(message);
|
// sendVpnExtensionMessage(message);
|
||||||
|
|
||||||
|
|
||||||
BOOL started = [m_currentTunnel.connection startVPNTunnelWithOptions:nil andReturnError:&startError];
|
BOOL started = [m_currentTunnel.connection startVPNTunnelWithOptions:nil andReturnError:&startError];
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ namespace amnezia
|
|||||||
constexpr char psk_key[] = "psk_key";
|
constexpr char psk_key[] = "psk_key";
|
||||||
constexpr char mtu[] = "mtu";
|
constexpr char mtu[] = "mtu";
|
||||||
constexpr char allowed_ips[] = "allowed_ips";
|
constexpr char allowed_ips[] = "allowed_ips";
|
||||||
|
constexpr char persistent_keep_alive[] = "persistent_keep_alive";
|
||||||
|
|
||||||
constexpr char client_ip[] = "client_ip"; // internal ip address
|
constexpr char client_ip[] = "client_ip"; // internal ip address
|
||||||
|
|
||||||
|
|||||||
@@ -305,6 +305,11 @@ QJsonObject VpnConnection::createVpnConfiguration(int serverIndex, const ServerC
|
|||||||
// TODO: try to get hostName, port, description for 3rd party configs
|
// TODO: try to get hostName, port, description for 3rd party configs
|
||||||
// vpnConfiguration[config_key::port] = ...;
|
// vpnConfiguration[config_key::port] = ...;
|
||||||
|
|
||||||
|
#if defined Q_OS_IOS
|
||||||
|
QJsonObject awg = server[config_key::containers].toArray().first().toObject()[config_key::awg].toObject();
|
||||||
|
QString mtu = awg[config_key::mtu].toString(protocols::awg::defaultMtu);
|
||||||
|
vpnConfiguration[config_key::mtu] = mtu;
|
||||||
|
#endif
|
||||||
return vpnConfiguration;
|
return vpnConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user