-
-
Save IhorYachmenov/fb63fd19f30541780950b6670e8a2865 to your computer and use it in GitHub Desktop.
import Foundation | |
import NetworkExtension | |
class VPNIKEv2Setup { | |
static let shared = VPNIKEv2Setup() | |
let vpnManager = NEVPNManager.shared() | |
func initVPNTunnelProviderManager() { | |
print("CALL LOAD TO PREFERENCES...") | |
self.vpnManager.loadFromPreferences { [self] (error) -> Void in | |
if((error) != nil) { | |
print("VPN Preferences error: 1 - \(String(describing: error))") | |
} else { | |
let IKEv2Protocol = NEVPNProtocolIKEv2() | |
IKEv2Protocol.authenticationMethod = .certificate | |
IKEv2Protocol.serverAddress = VPNServerSettings.shared.vpnServerAddress | |
IKEv2Protocol.remoteIdentifier = VPNServerSettings.shared.vpnRemoteIdentifier | |
IKEv2Protocol.localIdentifier = VPNServerSettings.shared.vpnLocalIdentifier | |
IKEv2Protocol.useExtendedAuthentication = false | |
IKEv2Protocol.ikeSecurityAssociationParameters.encryptionAlgorithm = .algorithmAES256GCM | |
IKEv2Protocol.ikeSecurityAssociationParameters.diffieHellmanGroup = .group20 | |
IKEv2Protocol.ikeSecurityAssociationParameters.integrityAlgorithm = .SHA512 | |
IKEv2Protocol.ikeSecurityAssociationParameters.lifetimeMinutes = 1440 | |
IKEv2Protocol.childSecurityAssociationParameters.encryptionAlgorithm = .algorithmAES256GCM | |
IKEv2Protocol.childSecurityAssociationParameters.diffieHellmanGroup = .group20 | |
IKEv2Protocol.childSecurityAssociationParameters.integrityAlgorithm = .SHA512 | |
IKEv2Protocol.childSecurityAssociationParameters.lifetimeMinutes = 1440 | |
IKEv2Protocol.deadPeerDetectionRate = .medium | |
IKEv2Protocol.disableRedirect = true | |
IKEv2Protocol.disableMOBIKE = false | |
IKEv2Protocol.enableRevocationCheck = false | |
IKEv2Protocol.enablePFS = true | |
IKEv2Protocol.useConfigurationAttributeInternalIPSubnet = false | |
IKEv2Protocol.serverCertificateIssuerCommonName = VPNServerSettings.shared.vpnServerCertificateIssuerCommonName | |
IKEv2Protocol.disconnectOnSleep = false | |
IKEv2Protocol.certificateType = .ECDSA384 | |
IKEv2Protocol.identityDataPassword = VPNServerSettings.shared.p12Password | |
IKEv2Protocol.identityData = self.dataFromFile() | |
self.vpnManager.protocolConfiguration = IKEv2Protocol | |
self.vpnManager.localizedDescription = "Venom VPN" | |
self.vpnManager.isEnabled = true | |
self.vpnManager.isOnDemandEnabled = false | |
//Set rules | |
var rules = [NEOnDemandRule]() | |
let rule = NEOnDemandRuleConnect() | |
rule.interfaceTypeMatch = .any | |
rules.append(rule) | |
// self.vpnManager.onDemandRules = rules | |
print("SAVE TO PREFERENCES...") | |
//SAVE TO PREFERENCES... | |
self.vpnManager.saveToPreferences(completionHandler: { (error) -> Void in | |
if((error) != nil) { | |
print("VPN Preferences error: 2 - \(String(describing: error))") | |
} else { | |
print("CALL LOAD TO PREFERENCES AGAIN...") | |
//CALL LOAD TO PREFERENCES AGAIN... | |
self.vpnManager.loadFromPreferences(completionHandler: { (error) in | |
if ((error) != nil) { | |
print("VPN Preferences error: 2 - \(String(describing: error))") | |
} else { | |
var startError: NSError? | |
do { | |
//START THE CONNECTION... | |
try self.vpnManager.connection.startVPNTunnel() | |
} catch let error as NSError { | |
startError = error | |
print(startError.debugDescription) | |
} catch { | |
print("Fatal Error") | |
fatalError() | |
} | |
if ((startError) != nil) { | |
print("VPN Preferences error: 3 - \(String(describing: error))") | |
//Show alert here | |
print("title: Oops.., message: Something went wrong while connecting to the VPN. Please try again.") | |
print(startError.debugDescription) | |
} else { | |
print("Starting VPN...") | |
} | |
} | |
}) | |
} | |
}) | |
} | |
} | |
} | |
//MARK:- Connect VPN | |
static func connectVPN() { | |
VPNIKEv2Setup().initVPNTunnelProviderManager() | |
} | |
//MARK:- Disconnect VPN | |
static func disconnectVPN() { | |
VPNIKEv2Setup().vpnManager.connection.stopVPNTunnel() | |
} | |
//MARK:- Disconnect VPN | |
static func testConnect() { | |
do { | |
try VPNIKEv2Setup().vpnManager.connection.startVPNTunnel() | |
} catch let error { | |
print(error) | |
} | |
} | |
//MARK:- check connection staatus | |
static func checkStatus() { | |
let status = VPNIKEv2Setup().vpnManager.connection.status | |
print("VPN connection status = \(status.rawValue)") | |
switch status { | |
case NEVPNStatus.connected: | |
print("Connected") | |
case NEVPNStatus.invalid, NEVPNStatus.disconnected : | |
print("Disconnected") | |
case NEVPNStatus.connecting , NEVPNStatus.reasserting: | |
print("Connecting") | |
case NEVPNStatus.disconnecting: | |
print("Disconnecting") | |
default: | |
print("Unknown VPN connection status") | |
} | |
} | |
func dataFromFile() -> Data? { | |
let rootCertPath = Bundle.main.url(forResource: "phone", withExtension: "p12") | |
print(rootCertPath?.absoluteURL as Any) | |
return try? Data(contentsOf: rootCertPath!.absoluteURL) | |
} | |
} | |
class VPNServerSettings: NSObject { | |
static let shared = VPNServerSettings() | |
let p12Password = "*****" // password from file certificate "****.p12" | |
let vpnServerAddress = "******" | |
let vpnRemoteIdentifier = "*******" // In my case same like vpn server address | |
let vpnLocalIdentifier = "phone@caf1e9*******.algo" | |
let vpnServerCertificateIssuerCommonName = "*******" // In my case same like vpn server address | |
} |
Dearimranullah
commented
Nov 6, 2023
via email
@Dearimranullah select your Target than tab "Signing & Capabilities" and you should enable capability "Network Extension -> and check Packet Tunnel" and add another one capability "Personal VPN", and in your entitlements file add "Outgoing Network Connections" - > YES, maybe last step will added automatically can't recall that. Then when you will call loadFromPreferences you should see alert with permission access
How do I use it in content view? Can you give me an example?
@Rayan25062011 Hi, in this realization VPNIKEv2Setup is Singelton because you can call any non-static function such as VPNIKEv2Setup.initVPNTunnelProviderManager.initVPNTunnelProviderManager(), and after that in any comfortable place use VPNIKEv2Setup. connectVPN() and disconnectVPN() etc., or rewrite realization for your requirements
@Rayan25062011 Hi, in this realization VPNIKEv2Setup is Singelton because you can call any non-static function such as VPNIKEv2Setup.initVPNTunnelProviderManager.initVPNTunnelProviderManager(), and after that in any comfortable place use VPNIKEv2Setup. connectVPN() and disconnectVPN() etc., or rewrite realization for your requirements
Thank you very much @IhorYachmenov