如何检测iphone的VPN连接?

时间:2013-04-29 17:50:52

标签: iphone ios objective-c vpn

我需要以编程方式检测iphone是否连接到VPN。我正在开发一个尝试加载URL的应用程序,此页面仅在设备连接到VPN时打开。在加载此URL之前,我需要检查VPN连接。我尝试了以下内容。但这并没有像预期的那样发挥作用。

- (BOOL)checkForVPNConnectivity {
  NSDictionary *dict = (__bridge NSDictionary *)(CFNetworkCopySystemProxySettings());
  //NSLog(@"cfnetwork proxy setting : %@", dict);
  return [dict count] > 0; 
 }

4 个答案:

答案 0 :(得分:4)

我不认为应该通过检查CFNetworkCopySystemProxySettings()中的非零数量的元素来确定VPN连接。 (例如,我在WiFi网络上看到条目,但在VPN上看不到。)

所以,有两个观察结果:

  1. 我会考虑使用SystemConfiguration.framework并将以下代码与VPN上的某些主机名一起使用:

    - (BOOL)checkForConnectivity:(NSString *)hostName
    {
        BOOL success = false;
    
        SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);
        SCNetworkReachabilityFlags flags;
        success = SCNetworkReachabilityGetFlags(reachability, &flags);
        CFRelease(reachability);
    
        NSLog(@"success=%x", flags);
    
        // this is the standard non-VPN logic, you might have to alter it for VPN connectivity
    
        BOOL isAvailable = success && (flags & kSCNetworkFlagsReachable) && !(flags & kSCNetworkFlagsConnectionRequired);
        if (isAvailable) {
            NSLog(@"Host is reachable: %d", flags);
            return YES;
        }else{
            NSLog(@"Host is unreachable");
            return NO;
        }
    }
    

    假设success非零,您可能需要对flags中位的设置进行一些实证研究。有关这些标志的技术定义,请参阅SCNetworkReachability Reference。我已经听说过在VPN连接时他们得到kSCNetworkReachabilityFlagsReachable | kSCNetworkReachabilityFlagsTransientConnection,但我没有VPN,所以我无法测试这个说法。我建议尝试使用和不使用VPN,并查看是否返回了不同的flags

  2. 与手头的问题无关,您的代码示例会泄漏。如果使用ARC,请不要忘记使用CFBridgingRelease__bridge_transfer。或者无论是否在ARC中,在返回之前明确地调用CFRelease

    如果您运行静态分析仪(按 shift + 命令 + B 或选择"分析"来自& #34;产品"菜单)在Xcode的最新版本中,它应该警告你关于Core Foundation调用的内存管理。

    无论如何,这就是我倾向于在ARC中处理它的方式:

    - (BOOL)checkForVPNConnectivity
    {
        NSDictionary *dict = CFBridgingRelease(CFNetworkCopySystemProxySettings());
    
        return [dict count] > 0;
    }
    

答案 1 :(得分:0)

您可以针对上述问题使用简单的解决方法。

只需使用apple reachability检查ios设备是否已连接到互联网。如果没有丢失互联网连接错误。如果是,请尝试使用NSURLConnection访问您的VPN依赖URL。如果您获得成功200,即您连接到VPN。如果此请求返回主机未找到或任何错误,如-1001意味着您没有连接到VPN。然后您可以向用户抛出相应的VPN连接错误。快乐编码.... Arun kumar

有关更多信息,请参阅我的博客 http://aruntheiphonedeveloper.blogspot.in

答案 2 :(得分:0)

let connect=ConnectVPN()
        connect.loadFromPreference()
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            let status=NEVPNManager.shared().connection.status
            print(status)
        }

负载偏好为

 public func loadFromPreference(){
        do {
            try self.vpnManager.loadFromPreferences(completionHandler: {
                error in
            })

        } catch let error {
            print("Could not start VPN Connection: \(error.localizedDescription)" )
        }
    }

然后处于状态,您将获得已断开连接,无效和已连接等的vpn状态,您可以通过此链接查看https://developer.apple.com/documentation/networkextension/nevpnstatus 希望对你有帮助 快乐的编码:)

答案 3 :(得分:0)

简单使用这个方法你就可以实现。 自 iOS 12 和 iOS 13 以来,密钥列表已更改

已添加 2 个键

utun1 和 utun2

所以函数应该是:

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

}