13

I am creating a VPN connection in Swift with the on demand connect rule below:

        let config = NEVPNProtocolIPSec()
        config.serverAddress = ""
        config.username = ""
        config.passwordReference = ""
        config.authenticationMethod = .sharedSecret
        config.sharedSecretReference = ""
        config.useExtendedAuthentication = true
        config.disconnectOnSleep = true

        let connectRule = NEOnDemandRuleConnect()
        connectRule.interfaceTypeMatch = .any
        vpnManager.onDemandRules = [connectRule]

        vpnManager.protocolConfiguration = config
        vpnManager.localizedDescription = ""
        vpnManager.isOnDemandEnabled = true
        vpnManager.isEnabled = true

This connection works fine. If I am using WiFi it reconnects after disconnecting from WiFi but not vice versa. If am using cellular connection and try to activate WiFi, the phone does not connect to WiFi until I disconnect it from the VPN manually. I believe an active VPN connection blocks switching from 4G to WiFi.

How can I resolve this issue?

Alessi 42
  • 1,112
  • 11
  • 26
mTuran
  • 1,846
  • 4
  • 32
  • 58

1 Answers1

6

At the extension, add an observer for defaultPath. Then you will be notified when the interface changes, and you would be able to reconnect with WIFI

Edit: example code

//add observer
let options = NSKeyValueObservingOptions([.new, .old])
self.addObserver(self, forKeyPath: "defaultPath", options: options, context: nil)

//detect interface changes
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if let keyPath = keyPath {
            if keyPath == "defaultPath" {
                let oldPath = change?[.oldKey] as! NWPath
                let newPath = change?[.newKey] as! NWPath
                //expensive is 3g, not expensive is wifi
                if !oldPath.isEqual(to: newPath)) {
                  //disconnect the VPN, maybe with cancelTunnelWithError
                }
            }
       }
}
Witterquick
  • 6,048
  • 3
  • 26
  • 50
  • Hello Roee84, Could you please give me example code for this ? – mTuran May 27 '17 at 17:35
  • @Roee84 Apart from that, do I have to take into consideration other aspects in order to have a VPN that is always connected? Because I see that they disconnect from time to time. Thanks – Ricardo Jul 15 '18 at 15:58
  • 1
    @Ricardo the example at the question should be enough for "always connected", something like: let connectRule = NEOnDemandRuleConnect() connectRule.interfaceTypeMatch = .any vpnManager.onDemandRules = [connectRule] vpnManager.isOnDemandEnabled = true – Witterquick Jul 15 '18 at 20:01
  • @Roee84 Thanks. It seems it works, now I see the VPN icon all the time, even if I restart the iphone. The problem I have now is that after several hours of use or changing wifi to 3g and similar, sometimes I see this in the console: "error 21:19:25.226644 +0100 Domain Checker Extension __nw_socket_service_writes_block_invoke sendmsg(fd 5, 40 bytes): [51] Network is unreachable" and it does not work again untill I restart manually. Any idea? Should I use KVO applied to defaultPath to solve that. Thanks a lot. – Ricardo Jul 21 '18 at 18:55
  • No idea what is this err, but try with defaultPath to detect those changes, maybe it will solve your problem – Witterquick Jul 22 '18 at 07:26