openVPN меняет статус с подключенного к отключенному напрямую в iOS - PullRequest
0 голосов
/ 18 марта 2020

Я пытаюсь подключиться к vpn по протоколу openVPN, загрузив нижеприведенный файл .ovpn. Код, через который я пытаюсь подключиться к серверу openVPN, но не смог, потому что он изменяет состояние с подключения на отключение, а затем отключает код:

var Manager:NETunnelProviderManager? //global variable

    override func viewDidLoad() {
    super.viewDidLoad()
    Keychain.set("password".data(using: String.Encoding.utf8)!, forKey: "password")
    NETunnelProviderManager.loadAllFromPreferences { (Managers, error) in
        if error == nil
        {
            self.Manager = Managers?.last ?? NETunnelProviderManager()
        }
        else
        {
            print(error?.localizedDescription)
        }
    }
    NotificationCenter.default.addObserver(forName: NSNotification.Name.NEVPNStatusDidChange, object: self.Manager?.connection, queue: OperationQueue.main) { (notification) in
        print(self.Manager?.connection.status.description ?? "Unknown State")
        if self.Manager?.connection.status.description ?? "" == "Disconnected"
        {
            self.Manager?.connection.stopVPNTunnel()
        }
    }

    connect.addTarget(self, action: #selector(self.connectToVPN), for: .touchUpInside)
}

@objc func connectToVPN() //called on onclick of button
{
    let proto = NETunnelProviderProtocol.init()
    self.Manager?.loadFromPreferences(completionHandler: { (Error) in
        if Error == nil
        {
            guard let configFile = Bundle.main.url(forResource: ovpn filename, withExtension: "ovpn") else {return}
            do {
                let filedata = try Data.init(contentsOf: configFile)
                proto.providerConfiguration = ["ovpn":filedata]
            } catch  {
                print(error)
            }

            proto.serverAddress = "server Address"
            proto.providerBundleIdentifier = "demo.TTS.VPndemo.vpntunnelDemo"
            proto.username = "" //Username
            proto.passwordReference = self.Keychain.getData("password")
            proto.disconnectOnSleep = false

            self.Manager?.protocolConfiguration = proto
            self.Manager?.isEnabled = true
            self.Manager?.isOnDemandEnabled = true
            self.Manager?.localizedDescription = "DemoVPN"

            self.Manager?.saveToPreferences(completionHandler: { (error) in
                if error == nil
                {
                    self.Manager?.loadFromPreferences(completionHandler: { (error) in
                        if error == nil
                        {
                            do {
                                try self.Manager?.connection.startVPNTunnel()
                            } catch  {
                                print(error.localizedDescription)
                            }

                        }
                        else
                        {
                            print(error?.localizedDescription)
                        }
                    })
                }
                else
                {
                    print(error?.localizedDescription)
                }
            })
        }
        else
        {
            print(Error!)
        }
    })
}

Я также сделал расширение сети, но я думаю, что оно не работает, так как у меня там нет точки останова

import NetworkExtension
import OpenVPNAdapter

  class PacketTunnelProvider: NEPacketTunnelProvider {

 lazy var vpnAdapter: OpenVPNAdapter = {
       let adapter = OpenVPNAdapter()
       adapter.delegate = self

       return adapter
   }()

   let vpnReachability = OpenVPNReachability()

   var startHandler: ((Error?) -> Void)?
   var stopHandler: (() -> Void)?

override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) {

    guard
        let protocolConfiguration = protocolConfiguration as? NETunnelProviderProtocol,
        let providerConfiguration = protocolConfiguration.providerConfiguration
    else {
        fatalError()
    }

    guard let ovpnFileContent: Data = providerConfiguration["ovpn"] as? Data else {
        fatalError()
    }

    let configuration = OpenVPNConfiguration()
    configuration.fileContent = ovpnFileContent

    // Add this line if you want to keep TUN interface active during pauses or reconnections
    configuration.tunPersist = true

    // Apply OpenVPN configuration
    let properties: OpenVPNProperties
    do {
        properties = try vpnAdapter.apply(configuration: configuration)
    } catch {
        completionHandler(error)
        return
    }

    // Provide credentials if needed
    if !properties.autologin {
        // If your VPN configuration requires user credentials you can provide them by
        // `protocolConfiguration.username` and `protocolConfiguration.passwordReference`
        // properties. It is recommended to use persistent keychain reference to a keychain
        // item containing the password.

        guard let username: String = protocolConfiguration.username else {
            fatalError()
        }

        // Retrieve a password from the keychain
        guard let password: String = protocolConfiguration.identityDataPassword else {
            fatalError()
        }

        let credentials = OpenVPNCredentials()
        credentials.username = username
        credentials.password = password

        do {
            try vpnAdapter.provide(credentials: credentials)
        } catch {
            completionHandler(error)
            return
        }
    }

    // Checking reachability. In some cases after switching from cellular to
    // WiFi the adapter still uses cellular data. Changing reachability forces
    // reconnection so the adapter will use actual connection.
    vpnReachability.startTracking { [weak self] status in
        guard status != .notReachable else { return }
        self?.vpnAdapter.reconnect(afterTimeInterval: 5)
    }

    // Establish connection and wait for .connected event
    startHandler = completionHandler
    vpnAdapter.connect()



}

override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
    stopHandler = completionHandler

    if vpnReachability.isTracking {
        vpnReachability.stopTracking()
    }

    vpnAdapter.disconnect()
}

override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)?) {
    // Add code here to handle the message.
    if let handler = completionHandler {
        handler(messageData)
    }
}

override func sleep(completionHandler: @escaping () -> Void) {
    // Add code here to get ready to sleep.
    completionHandler()
}

override func wake() {
    // Add code here to wake up.
}
}

 extension PacketTunnelProvider: OpenVPNAdapterDelegate {

// OpenVPNAdapter calls this delegate method to configure a VPN tunnel.
// `completionHandler` callback requires an object conforming to `OpenVPNAdapterPacketFlow`
// protocol if the tunnel is configured without errors. Otherwise send nil.
// `OpenVPNAdapterPacketFlow` method signatures are similar to `NEPacketTunnelFlow` so
// you can just extend that class to adopt `OpenVPNAdapterPacketFlow` protocol and
// send `self.packetFlow` to `completionHandler` callback.
func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, configureTunnelWithNetworkSettings networkSettings: NEPacketTunnelNetworkSettings?, completionHandler: @escaping (OpenVPNAdapterPacketFlow?) -> Void) {
    // In order to direct all DNS queries first to the VPN DNS servers before the primary DNS servers
    // send empty string to NEDNSSettings.matchDomains
    //networkSettings?.dnsSettings?.matchDomains = [""]

    // Specify the network settings for the current tunneling session.
//        setTunnelNetworkSettings(settings) { (error) in
//            completionHandler(error == nil ? self.packetFlow : nil)
//        }
}

// Process events returned by the OpenVPN library
func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleEvent event: OpenVPNAdapterEvent, message: String?) {
    switch event {
    case .connected:
        if reasserting {
            reasserting = false
        }

        guard let startHandler = startHandler else { return }

        startHandler(nil)
        self.startHandler = nil

    case .disconnected:
        guard let stopHandler = stopHandler else { return }

        if vpnReachability.isTracking {
            vpnReachability.stopTracking()
        }

        stopHandler()
        self.stopHandler = nil

    case .reconnecting:
        reasserting = true

    default:
        break
    }
}

// Handle errors thrown by the OpenVPN library
func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleError error: Error) {
    // Handle only fatal errors
    guard let fatal = (error as NSError).userInfo[OpenVPNAdapterErrorFatalKey] as? Bool, fatal == true else {
        return
    }

    if vpnReachability.isTracking {
        vpnReachability.stopTracking()
    }

    if let startHandler = startHandler {
        startHandler(error)
        self.startHandler = nil
    } else {
        cancelTunnelWithError(error)
    }
}

// Use this method to process any log message returned by OpenVPN library.
func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleLogMessage logMessage: String) {
    // Handle log messages
}

}
...