Check whether device is connected to a VPN in iOS 12

Viewed 2339

I am using the code below (Swift 3 and Swift 4 compatible) to check the VPN connection on iOS devices which is not working in iOS 12 and above. How can I check the vpn connectivity in iOS 12

func isVPNConnected() -> Bool {
    let cfDict = CFNetworkCopySystemProxySettings()
    let nsDict = cfDict!.takeRetainedValue() as NSDictionary
    let keys = nsDict["__SCOPED__"] as! NSDictionary

    for key: String in keys.allKeys as! [String] {
        if (key == "tap" || key == "tun" || key == "ppp" || key == "ipsec" || key == "ipsec0") {
            return true
        }
    }
    return false
}

Thank you for your help.

3 Answers

The list of keys has been changed since iOS 12 and iOS 13

2 keys have been added

utun1 and utun2

so the function should be:

static func isConnectedToVPN() -> Bool {

    let cfDict = CFNetworkCopySystemProxySettings()
    let nsDict = cfDict!.takeRetainedValue() as NSDictionary
    let keys = nsDict["__SCOPED__"] as! NSDictionary
    for key: String in keys.allKeys as! [String] {
           if (key == "tap" || key == "tun" || key == "ppp" || key == "ipsec" || key == "ipsec0" || key == "utun1" || key == "utun2") {
               return true
           }
       }
       return false
}

Trying adding the key 'utun1' to your check (or prefixed with 'utun' followed by a number).

for key: String in keys.allKeys as! [String] {
    if (key == "tap" || key == "tun" || key == "ppp" || key == "ipsec" || key == "ipsec0" || key == "utun1") {
        return true
    }
}
return false

In my case, I was receiving an ipsec4 and the app wasn't recognizing the VPN. Therefore I came up with something a bit different:

struct VpnChecker {

    private static let vpnProtocolsKeysIdentifiers = [
        "tap", "tun", "ppp", "ipsec", "utun"
    ]

    static func isVpnActive() -> Bool {
        guard let cfDict = CFNetworkCopySystemProxySettings() else { return false }
        let nsDict = cfDict.takeRetainedValue() as NSDictionary
        guard let keys = nsDict["__SCOPED__"] as? NSDictionary,
            let allKeys = keys.allKeys as? [String] else { return false }

        // Checking for tunneling protocols in the keys
        for key in allKeys {
            for protocolId in vpnProtocolsKeysIdentifiers
                where key.starts(with: protocolId) {
                // I use start(with:), so I can cover also `ipsec4`, `ppp0`, `utun0` etc...
                return true
            }
        }
        return false
    }
}

Usage: VpnChecker.isVpnActive()

I also wrote a little blog post about it here

Related