We are trying to connecting vpn (TCP & UDP) through “.ovpn” configuration using TunnelKit, But after calling startTunnel NEPacketTunnelProvider is not initiating.
Here's code:
private func makeProtocol() -> NETunnelProviderProtocol {
let credentials = OpenVPN.Credentials(textUsername.text!, textPassword.text!)
let configurationFileURL = Bundle.main.url(forResource: “xyz”, withExtension: "ovpn")
do {
let file = try OpenVPN.ConfigurationParser.parsed(fromURL: configurationFileURL!).configuration
var builder = OpenVPNTunnelProvider.ConfigurationBuilder(sessionConfiguration: file)
builder.mtu = 1450
builder.shouldDebug = true
builder.masksPrivateData = false
let configuration = builder.build()
return try! configuration.generatedTunnelProtocol(
withBundleIdentifier: ViewController2.tunnelIdentifier,
appGroup: ViewController2.appGroup,
credentials: credentials
)
} catch {
print("Failed to send a message to the provider")
return NETunnelProviderProtocol()
}
}
func connect() {
configureVPN({ (manager) in
return self.makeProtocol()
}, completionHandler: { (error) in
if let error = error {
print("configure error: \(error)")
return
}
self.currentManager?.isEnabled = true
let session = self.currentManager?.connection as! NETunnelProviderSession
do {
try session.startTunnel()
print("start Tunnel called")
} catch let e {
print("error starting tunnel: \(e)")
}
})
}
Related
I'm creating a VPN app in Mac Catalyst.
The demo works fine on the iOs platform but when I run on make catalyst, VPN status changes to Connecting... and then Disconnected....
The same code also works in macOS separate project.
I've used NETunnelProviderManager
Here is the demo.
https://github.com/anismansuri63/DNS-Forwarding
public func establishConnection(extensionBundleID: String) {
tunnelBundleId = extensionBundleID
initVPNTunnelProviderManager()
}
private func initVPNTunnelProviderManager(completionHandler: VoidHandler? = nil) {
NETunnelProviderManager.loadAllFromPreferences { (savedManagers: [NETunnelProviderManager]?, error: Error?) in
if let error = error {
print(error)
}
if let savedManagers = savedManagers {
if savedManagers.count > 0 {
self.vpnManager = savedManagers[0]
}
}
self.vpnManager.loadFromPreferences(completionHandler: { (error:Error?) in
if let error = error {
print(error)
}
let providerProtocol = NETunnelProviderProtocol()
providerProtocol.providerBundleIdentifier = self.tunnelBundleId
providerProtocol.providerConfiguration = [
"server": self.serverAddress,
"dns": self.dns
]
providerProtocol.serverAddress = self.serverAddress
self.vpnManager.protocolConfiguration = providerProtocol
self.vpnManager.localizedDescription = "Family Protection"
self.vpnManager.isEnabled = true
self.vpnManager.saveToPreferences(completionHandler: { (error:Error?) in
if let error = error {
print(error)
} else {
print("Save successfully")
completionHandler?()
}
})
self.VPNStatusDidChange(nil)
})
}
NotificationCenter.default.addObserver(self, selector: #selector(VPNStatusDidChange(_:)), name: NSNotification.Name.NEVPNStatusDidChange, object: nil)
}
public func enableProtection() {
self.vpnManager.loadFromPreferences { [weak self] error in
if let error = error {
print(error)
}
do {
try self?.vpnManager.connection.startVPNTunnel()
} catch {
self?.initVPNTunnelProviderManager(completionHandler: {
self?.enableProtection()
})
print(error)
}
}
}
I am trying to search for UPnP devices in my network by sending an SSDP discovery packet. I can send them but I do not receive responses from devices and I do not know what I am missing. Maybe someone here can help me out. Goal is not to use any external libaries (pods, spm, ...).
Here is what I have:
import UIKit
import Network
extension NWEndpoint.Port {
static let ssdp: NWEndpoint.Port = 1_900
}
extension NWEndpoint.Host {
static let ssdp: NWEndpoint.Host = "239.255.255.250"
}
class ViewController: UIViewController {
private let parameters: NWParameters = {
let parameters: NWParameters = .udp
parameters.allowLocalEndpointReuse = true
parameters.allowFastOpen = true
return parameters
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBackground
do {
try setupConnection()
} catch {
print(error.localizedDescription)
}
}
private func setupConnection() throws {
let endpoints: [NWEndpoint] = [
.hostPort(host: .ssdp, port: .ssdp)
]
let multicast = try NWMulticastGroup(for: endpoints)
let group = NWConnectionGroup(with: multicast, using: parameters)
group.setReceiveHandler(maximumMessageSize: 16384, rejectOversizedMessages: true) { (message, content, isComplete) in
print("Received message from \(String(describing: message.remoteEndpoint))")
}
group.stateUpdateHandler = { [weak viewController = self] (state) in
guard let viewController = viewController else {
return
}
switch state {
case .setup:
print("Setup")
case .waiting(let error):
let message = String(format: "Waiting: %#", error.localizedDescription)
print(message)
case .ready:
print("Ready")
viewController.send(to: group)
case .failed(let error):
let message = String(format: "Failed: %#", error.localizedDescription)
print(message)
case .cancelled:
print("Cancelled")
#unknown default:
print("Unknown group state")
}
}
group.start(queue: .main)
}
private func send(to group: NWConnectionGroup) {
let message = "M-SEARCH * HTTP/1.1\r\nST: ssdp:all\r\nHOST: 239.255.255.250:1900\r\nMAN: \"ssdp:discover\"\r\nMX: 1\r\n\r\n"
let payload = message.data(using: .utf8)
group.send(content: payload) { error in
let message: String
if let error = error {
message = String(format: "Send completed with error %#", error.localizedDescription)
} else {
message = String(format: "Send completed")
}
print(message)
}
}
}
any help is appreciated! thank you in the meantime.
Edit: This does not work either
import UIKit
import Network
extension NWEndpoint.Port {
static let ssdp: NWEndpoint.Port = 1_900
}
extension NWEndpoint.Host {
static let ssdp: NWEndpoint.Host = "239.255.255.250"
}
class ViewController: UIViewController {
private let connectionQueue = DispatchQueue(label: "Connection")
private let listenerQueue = DispatchQueue(label: "Listener")
private let parameters: NWParameters = {
let parameters: NWParameters = .udp
parameters.allowLocalEndpointReuse = true
return parameters
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBackground
do {
try setupConnection()
} catch {
print(error.localizedDescription)
}
}
private func setupConnection() throws {
let listener = try NWListener(using: parameters)
listener.stateUpdateHandler = { state in
print("l-state", state)
}
listener.newConnectionHandler = { (connection) in
print("connection", connection)
}
listener.start(queue: listenerQueue)
let connection = NWConnection(host: .ssdp, port: .ssdp, using: parameters)
connection.stateUpdateHandler = { [weak viewController = self] state in
print("c-state", state)
guard let viewController = viewController else {
return
}
switch state {
case .ready:
viewController.send(to: connection)
default: return
}
}
connection.start(queue: connectionQueue)
}
private func send(to connection: NWConnection) {
let message = "M-SEARCH * HTTP/1.1\r\nSt: ssdp:all\r\nHost: 239.255.255.250:1900\r\nMan: \"ssdp:discover\"\r\nMX: 1\r\n\r\n"
let payload = message.data(using: .utf8)
connection.send(content: payload, completion: .contentProcessed { error in
if let error = error {
print(error.localizedDescription)
} else {
print("ok")
}
})
connection.receive(minimumIncompleteLength: 1, maximumLength: 65536) { data, context, isComplete, error in
print("data", data ?? "")
}
}
}
Hello I am working on an application which can intercept the visited network traffic ip address list from iPhone (similar to Charles Proxy).
Currently I have written code to create a VPN profile using NETunnelProviderManager class.
NETunnelProviderManager.loadAllFromPreferences { [weak self] managers, error in
guard let self = self else { return }
if self.manager != managers?.first {
self.manager = managers?.first
} else {
self.manager = self.makeManager()
}
self.manager?.saveToPreferences(completionHandler: { (error) in
if let error = error {
print("Error in saving VPN Config: \(error.localizedDescription)")
}
self.manager?.loadFromPreferences(completionHandler: { (error) in
if error == nil {
do {
try self.manager?.connection.startVPNTunnel()
} catch let vpnTunnelError {
print("Unable to start VPN Tunnel by error: \(vpnTunnelError.localizedDescription)")
}
} else {
print("Load From Preference Error")
}
})
})
}
}
private func makeManager() -> NETunnelProviderManager {
let manager = NETunnelProviderManager()
manager.localizedDescription = "NetworkTrafficVPN"
let proto = NETunnelProviderProtocol()
proto.providerBundleIdentifier = "com.NetworkTraffic.vpn-tunnel"
proto.serverAddress = "Network Traffic"
manager.protocolConfiguration = proto
let onDemandRule = NEOnDemandRuleConnect()
onDemandRule.interfaceTypeMatch = .any
manager.isOnDemandEnabled = true
manager.onDemandRules = [onDemandRule]
manager.isEnabled = true
return manager
}
Once I start the vpn tunnel (self.manager?.connection.startVPNTunnel()) from the created NETunnelProviderManager object
I get a callback in NEPacketTunnelProvider network extension method (startTunnel(options: [String : NSObject]?, completionHandler: #escaping (Error?) -> Void)).
I have created the NEPacketTunnelNetworkSettings inside startTunnel() method using the assigned IP address of the iPhone.
After calling the method self.setTunnelNetworkSettings(settings) { error in } I am getting network data callback inside
self.packetFlow.readPackets { (data, numbers) } method
class PacketTunnelProvider: NEPacketTunnelProvider {
// MARK: - Constants
let logger: Logger = Logger(subsystem: "NetworkTrafficSubsystem", category: "NetworkTrafficCategory")
let proxyServerPort: Int = 8888
let proxyServerAddress = "192.168.43.185" // Device assigned ip address
// MARK: - NEPacketTunnelProvider
override func startTunnel(options: [String : NSObject]?, completionHandler: #escaping (Error?) -> Void) {
let settings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: proxyServerAddress)
settings.tunnelOverheadBytes = 80
settings.mtu = 1400
settings.ipv4Settings = NEIPv4Settings(addresses: [proxyServerAddress], subnetMasks: ["255.255.255.255"])
settings.ipv4Settings?.includedRoutes = [NEIPv4Route.default()]
settings.ipv4Settings?.excludedRoutes = []
settings.dnsSettings = NEDNSSettings(servers: ["8.8.8.8", "8.8.4.4"])
settings.dnsSettings?.matchDomains = []
self.setTunnelNetworkSettings(settings) { error in
if let e = error {
self.logger.info("Settings error")
completionHandler(e)
} else {
self.logger.info("Settings set without error")
self.readPacketObjects()
completionHandler(nil)
}
}
}
private func readPacketObjects() {
self.packetFlow.readPackets { (data, numbers) in
self.logger.info("Inside readPackets completionHandler")
// Way to print the ip address from the received data array
self.packetFlow.writePackets(data, withProtocols: numbers)
self.readPacketObjects()
}
}
}
But I am unable to decode the data object from self.packetFlow.readPackets { (data, numbers) in } method.
So my question is that in order to read the IP address of all the visited network traffic is this the correct approach or I need to do something else.
If this is correct approach then let me know how to decode the received Data object.
If not then please suggest the correct way to achieve this functionality.
Any help would be appreciated thanks.
Open vpn not working properly. After configureVPN function start connection.startVpn part is run but nothing happened.But I would put in below
I also checked PacketTunnelProvider plist everthing seems perfect.
readFile function returns Data that receive from ovpn file.
Network extension entitlements also appended.
Any help would be great.
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.networkextension.packet-tunnel</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).PacketTunnelProvider</string>
</dict>
class ViewController: UIViewController {
var providerManager: NETunnelProviderManager!
override func viewDidLoad() {
super.viewDidLoad()
self.loadProviderManager {
self.configureVPN(serverAddress: "127.0.0.1", username: "uid", password: "pw123")
}
}
func loadProviderManager(completion:#escaping () -> Void) {
NETunnelProviderManager.loadAllFromPreferences { (managers, error) in
if error == nil {
self.providerManager = managers?.first ?? NETunnelProviderManager()
completion()
}
}
}
func configureVPN(serverAddress: String, username: String, password: String) {
guard let configData = self.readFile(path: "serverfile.ovpn") else { return }
print("configData\(configData)")
self.providerManager?.loadFromPreferences { error in
if error == nil {
let tunnelProtocol = NETunnelProviderProtocol()
tunnelProtocol.username = username
tunnelProtocol.serverAddress = serverAddress
tunnelProtocol.providerBundleIdentifier = "com.bgnmobi.openDeneme.Packet" // bundle id of the network extension target
tunnelProtocol.providerConfiguration = ["ovpn": configData, "username": username, "password": password]
tunnelProtocol.disconnectOnSleep = false
self.providerManager.protocolConfiguration = tunnelProtocol
self.providerManager.localizedDescription = "GuardillaVPN" // the title of the VPN profile which will appear on Settings
self.providerManager.isEnabled = true
self.providerManager.saveToPreferences(completionHandler: { (error) in
if error == nil {
self.providerManager.loadFromPreferences(completionHandler: { (error) in
do {
print("aSDFs34dasdsadsa")
try self.providerManager.connection.startVPNTunnel() // starts the VPN tunnel.
} catch let error {
print(error.localizedDescription)
}
})
} else {
print("asdasdsadsa")
print(error)
}
})
}
}
}
func readFile(path: String) -> Data? {
let mypath = Bundle.main.path(forResource: "serverfile", ofType: ".ovpn")
if let dir = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first{
let fileURL = dir.appendingPathComponent(mypath!)
//reading
do{
let text2 = try String(contentsOfFile: mypath!,encoding: String.Encoding.utf8)
print(text2)
let gerekliURL = URL(fileURLWithPath: mypath!)
print(gerekliURL)
return try Data(contentsOf: gerekliURL, options: .uncached)
}catch{
// print("can t read")
}
}
return nil
}
}
These parts would be match with your Target file. Be carefull in that point. That was a problem in my case and probably yours too.
private static let appGroup = "group.com.project.examplevpn"
private static let tunnelIdentifier = "com.project.examplevpn.Extension"
I am trying to create VPN connection in my app. I go through this link
https://developer.apple.com/documentation/networkextension/nevpnmanager
but did not find any official code to use NEVPNManager and even not found any tutorial to use this NEVPNManager.
I am new to VPN concept and don't know that much about it. so Can anyone give some solutions?
Here is a IKEv2 configuration of VPN using Network Extension (Without shared key and certificate) in Swift 4.2:
final class VPNHandler {
let vpnManager = NEVPNManager.shared()
func initVPNTunnelProviderManager() {
print("CALL LOAD TO PREFERENCES...")
self.vpnManager.loadFromPreferences { (error) -> Void in
if((error) != nil) {
print("VPN Preferences error: 1")
} else {
let IKEv2Protocol = NEVPNProtocolIKEv2()
IKEv2Protocol.username = vpnUser.username
IKEv2Protocol.serverAddress = vpnServer.serverID //server tunneling Address
IKEv2Protocol.remoteIdentifier = vpnServer.remoteID //Remote id
IKEv2Protocol.localIdentifier = vpnUser.localID //Local id
IKEv2Protocol.deadPeerDetectionRate = .low
IKEv2Protocol.authenticationMethod = .none
IKEv2Protocol.useExtendedAuthentication = true //if you are using sharedSecret method then make it false
IKEv2Protocol.disconnectOnSleep = false
//Set IKE SA (Security Association) Params...
IKEv2Protocol.ikeSecurityAssociationParameters.encryptionAlgorithm = .algorithmAES256
IKEv2Protocol.ikeSecurityAssociationParameters.integrityAlgorithm = .SHA256
IKEv2Protocol.ikeSecurityAssociationParameters.diffieHellmanGroup = .group14
IKEv2Protocol.ikeSecurityAssociationParameters.lifetimeMinutes = 1440
//IKEv2Protocol.ikeSecurityAssociationParameters.isProxy() = false
//Set CHILD SA (Security Association) Params...
IKEv2Protocol.childSecurityAssociationParameters.encryptionAlgorithm = .algorithmAES256
IKEv2Protocol.childSecurityAssociationParameters.integrityAlgorithm = .SHA256
IKEv2Protocol.childSecurityAssociationParameters.diffieHellmanGroup = .group14
IKEv2Protocol.childSecurityAssociationParameters.lifetimeMinutes = 1440
let kcs = KeychainService()
//Save password in keychain...
kcs.save(key: "VPN_PASSWORD", value: vpnUser.password)
//Load password from keychain...
IKEv2Protocol.passwordReference = kcs.load(key: "VPN_PASSWORD")
self.vpnManager.protocolConfiguration = IKEv2Protocol
self.vpnManager.localizedDescription = "Safe Login Configuration"
self.vpnManager.isEnabled = true
self.vpnManager.isOnDemandEnabled = true
//print(IKEv2Protocol)
//Set rules
var rules = [NEOnDemandRule]()
let rule = NEOnDemandRuleConnect()
rule.interfaceTypeMatch = .any
rules.append(rule)
print("SAVE TO PREFERENCES...")
//SAVE TO PREFERENCES...
self.vpnManager.saveToPreferences(completionHandler: { (error) -> Void in
if((error) != nil) {
print("VPN Preferences error: 2")
} 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")
} 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")
//Show alert here
print("title: Oops.., message: Something went wrong while connecting to the VPN. Please try again.")
print(startError.debugDescription)
} else {
//self.VPNStatusDidChange(nil)
print("Starting VPN...")
}
}
})
}
})
}
} //END OF .loadFromPreferences //
}
//MARK:- Connect VPN
static func connectVPN() {
VPNHandler().initVPNTunnelProviderManager()
}
//MARK:- Disconnect VPN
static func disconnectVPN() {
VPNHandler().vpnManager.connection.stopVPNTunnel()
}
//MARK:- check connection staatus
static func checkStatus() {
let status = VPNHandler().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")
}
}
}
Code for keychain:
//MARK:- Variables for keychain access
// Identifiers
let serviceIdentifier = "MySerivice"
let userAccount = "authenticatedUser"
let accessGroup = "MySerivice"
// Arguments for the keychain queries
var kSecAttrAccessGroupSwift = NSString(format: kSecClass)
let kSecClassValue = kSecClass as CFString
let kSecAttrAccountValue = kSecAttrAccount as CFString
let kSecValueDataValue = kSecValueData as CFString
let kSecClassGenericPasswordValue = kSecClassGenericPassword as CFString
let kSecAttrServiceValue = kSecAttrService as CFString
let kSecMatchLimitValue = kSecMatchLimit as CFString
let kSecReturnDataValue = kSecReturnData as CFString
let kSecMatchLimitOneValue = kSecMatchLimitOne as CFString
let kSecAttrGenericValue = kSecAttrGeneric as CFString
let kSecAttrAccessibleValue = kSecAttrAccessible as CFString
class KeychainService: NSObject {
func save(key:String, value:String) {
let keyData: Data = key.data(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue), allowLossyConversion: false)!
let valueData: Data = value.data(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue), allowLossyConversion: false)!
let keychainQuery = NSMutableDictionary();
keychainQuery[kSecClassValue as! NSCopying] = kSecClassGenericPasswordValue
keychainQuery[kSecAttrGenericValue as! NSCopying] = keyData
keychainQuery[kSecAttrAccountValue as! NSCopying] = keyData
keychainQuery[kSecAttrServiceValue as! NSCopying] = "VPN"
keychainQuery[kSecAttrAccessibleValue as! NSCopying] = kSecAttrAccessibleAlwaysThisDeviceOnly
keychainQuery[kSecValueData as! NSCopying] = valueData;
// Delete any existing items
SecItemDelete(keychainQuery as CFDictionary)
SecItemAdd(keychainQuery as CFDictionary, nil)
}
func load(key: String)->Data {
let keyData: Data = key.data(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue), allowLossyConversion: false)!
let keychainQuery = NSMutableDictionary();
keychainQuery[kSecClassValue as! NSCopying] = kSecClassGenericPasswordValue
keychainQuery[kSecAttrGenericValue as! NSCopying] = keyData
keychainQuery[kSecAttrAccountValue as! NSCopying] = keyData
keychainQuery[kSecAttrServiceValue as! NSCopying] = "VPN"
keychainQuery[kSecAttrAccessibleValue as! NSCopying] = kSecAttrAccessibleAlwaysThisDeviceOnly
keychainQuery[kSecMatchLimit] = kSecMatchLimitOne
keychainQuery[kSecReturnPersistentRef] = kCFBooleanTrue
var result: AnyObject?
let status = withUnsafeMutablePointer(to: &result) { SecItemCopyMatching(keychainQuery, UnsafeMutablePointer($0)) }
if status == errSecSuccess {
if let data = result as! NSData? {
if let value = NSString(data: data as Data, encoding: String.Encoding.utf8.rawValue) {
//print(value)
}
return data as Data;
}
}
return "".data(using: .utf8)!;
}
}
This tutorial help me to create VPN connection.
http://blog.moatazthenervous.com/create-a-vpn-connection-with-apple-swift/
VPN file for connection and disconnection
import Foundation
import NetworkExtension
// MARK: - NEVPNManager
// MARK: -
private var vpnLoadHandler: (Error?) -> Void { return
{ (error:Error?) in
if ((error) != nil) {
print("Could not load VPN Configurations")
self.removeToast()
return;
}
self.showToast(msg: STRINGVALUES.kCreatingConnection)
//VPN connection via Username password
let p = NEVPNProtocolIPSec()
let kcs = KeychainService()
p.authenticationMethod = NEVPNIKEAuthenticationMethod.sharedSecret
//For the security purpose added word xyz in password .so it should be remove while connecting
if self.selectedSever != nil{
self.selectedSever?.password = (self.selectedSever?.password.replacingOccurrences(of: "xyz", with: ""))!
p.username = self.selectedSever?.userName
p.serverAddress = self.selectedSever?.serverAddress
kcs.save(key: "SHARED", value: (self.selectedSever?.password)!)
kcs.save(key: "VPN_PASSWORD", value: (self.selectedSever?.password)!)
p.sharedSecretReference = kcs.load(key: STRINGVALUES.kShared)
p.passwordReference = kcs.load(key: STRINGVALUES.kVPN_Pswd)
p.useExtendedAuthentication = true
p.disconnectOnSleep = false
// Check for free subscriber
if self.selectedSever?.serverType == STRINGVALUES.VIP.lowercased() && !Singleton.checkForPaidReciept(){
self.disconnectVPN()
Helper.showAlert(sender: self, title: STRINGVALUES.AppName, message: AlertMessage.kValidateSubscription)
return
}
self.vpnManager.protocolConfiguration = p
self.vpnManager.localizedDescription = STRINGVALUES.AppName
self.vpnManager.isEnabled = true
self.vpnManager.saveToPreferences(completionHandler: self.vpnSaveHandler)
}else{
}
}
}
private var vpnSaveHandler: (Error?) -> Void { return
{ (error:Error?) in
if (error != nil) {
print("Could not save VPN Configurations")
self.removeToast()
return
} else {
do {
try self.vpnManager.connection.startVPNTunnel()
} catch let error {
print("Error starting VPN Connection \(error.localizedDescription)");
self.removeToast()
}
}
}
//self.vpnlock = false
}
public func connectVPN() {
//For no known reason the process of saving/loading the VPN configurations fails.On the 2nd time it works
do {
try self.vpnManager.loadFromPreferences(completionHandler: self.vpnLoadHandler)
} catch let error {
print("Could not start VPN Connection: \(error.localizedDescription)" )
self.removeToast()
}
}
public func disconnectVPN() ->Void {
vpnManager.connection.stopVPNTunnel()
}
func vpnConnectionStatusChanged(){
let status = self.vpnManager.connection.status
print("VPN connection status = \(status)")
switch status {
case NEVPNStatus.connected:
showToast(msg: STRINGVALUES.kConnected)
case NEVPNStatus.invalid, NEVPNStatus.disconnected :
showToast(msg: STRINGVALUES.kDisconnected)
case NEVPNStatus.connecting , NEVPNStatus.reasserting:
showToast(msg: STRINGVALUES.kConnecting)
case NEVPNStatus.disconnecting:
showToast(msg: STRINGVALUES.kDisconnecting)
default:
print("Unknown VPN connection status")
}
}