//
// VpnManager.swift
// code
//
// Created by me on 6/5/18.
// Copyright © 2018 me. All rights reserved.
//
import Foundation
import NetworkExtension
class VpnManager {
let serverAddress = "myvpndomain"
let serverPort = "80"
let mtu = "1500"
let ip = "10.0.0.2"
let subnet = "255.255.255.0"
let dns = ["8.8.8.8", "8.4.4.4"]
let providerBundleIdentifier = "com.example.project.NetworkTunnelClass"
let localizedDescription = "Description"
let username="username"
let password="password"
var manager:NETunnelProviderManager?
/**
Create an initial tunnel provider manager.
- returns: The default provider manager.
*/
func initializeTunnelProviderManager () {
NETunnelProviderManager.loadAllFromPreferences { (savedManagers: [NETunnelProviderManager]?, error: Error?) in
if let error = error {
print(error)
}
if let savedManagers = savedManagers {
if savedManagers.count > 0 {
//self.manager = savedManagers[0]
// print(self.manager?.localizedDescription)
}
}
if (self.manager == nil) {
self.manager = self.createTunnelProviderManager()
}
self.manager!.saveToPreferences(completionHandler: {(error) -> Void in
if(error != nil) {
print("Error saving to preferences")
} else {
self.manager!.loadFromPreferences(completionHandler: { (error) in
if (error != nil) {
print("Error loading from preferences")
} else {
do {
print("Trying to start")
self.initializeConnectionObserver()
try self.manager!.connection.startVPNTunnel()
} catch let error as NSError {
print(error)
} catch {
print("There was a fatal error")
}
}
})
}
})
}
}
/*
Observe the NEVPN status
*/
func initializeConnectionObserver () {
NotificationCenter.default.addObserver(forName: NSNotification.Name.NEVPNStatusDidChange, object: self.manager!.connection, queue: OperationQueue.main) { (notification) -> Void in
if self.manager!.connection.status == .invalid {
print("VPN configuration is invalid")
} else if self.manager!.connection.status == .disconnected {
print("VPN is disconnected.")
} else if self.manager!.connection.status == .connecting {
print("VPN is connecting...")
} else if self.manager!.connection.status == .reasserting {
print("VPN is reasserting...")
} else if self.manager!.connection.status == .disconnecting {
print("VPN is disconnecting...")
}
}
}
/**
Create an initial tunnel provider manager.
- returns: The default provider manager.
*/
func createTunnelProviderManager () -> NETunnelProviderManager {
let manager = NETunnelProviderManager()
manager.protocolConfiguration = createTunnelProviderProtocol()
manager.localizedDescription = localizedDescription
manager.isEnabled = true
return manager
}
/**
Create an initial tunnel provider protocol for the Tunnel Manager.
- returns: The default provider proticil.
*/
func createTunnelProviderProtocol () -> NETunnelProviderProtocol {
//TODO: Move
let passwordData = password.data(using: String.Encoding.utf8, allowLossyConversion: false)!
let attributes: [NSObject: AnyObject] = [
kSecAttrService : UUID().uuidString as AnyObject,
kSecValueData : passwordData as AnyObject,
kSecAttrAccessible : kSecAttrAccessibleAlways,
kSecClass : kSecClassGenericPassword,
kSecReturnPersistentRef : kCFBooleanTrue
]
var result: AnyObject?
let status = SecItemAdd(attributes as CFDictionary, &result)
if let newPersistentReference = result as? Data , status == errSecSuccess {
print(newPersistentReference)
}
let providerProtocol = NETunnelProviderProtocol()
providerProtocol.providerBundleIdentifier = providerBundleIdentifier
providerProtocol.serverAddress = serverAddress
providerProtocol.username = username
providerProtocol.passwordReference = result as? Data
providerProtocol.providerConfiguration = [
"dns": dns,
"ip": ip,
"mtu": mtu,
"port": serverPort,
"server": serverAddress,
"subnet": subnet
]
return providerProtocol
}
}
When trying to start the vpn, I keep recieving the error code: NEVPNErrorDomain Code=2, which translates to
/*! @const NEVPNErrorConfigurationDisabled The VPN configuration is not enabled. */
NEVPNErrorConfigurationDisabled = 2,
However, as you can see in the method: createTunnelProviderManager, I enable the VPN. What else is causing this error message to be thrown?
Thanks.