繁体   English   中英

检查设备是否连接到 VPN

[英]Check whether device is connected to a VPN

我可以使用以下方法检查设备是否已连接到互联网:

var connected: Bool = true
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)
let defaultRouteReachability = withUnsafePointer(&zeroAddress) {
    SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
}
var flags = SCNetworkReachabilityFlags()
if !SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) {
    connected = false
}
let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
let needsConnection = (flags.rawValue & UInt2(kSCNetworkFlagsConnectionRequired)) != 0

if isReachable && !needsConnection && connected {
    login(usernameTextField.text!, password: appPassword.text!, environment: environmentUrl)
} else {
    let alert = UIAlertView()
    alert.title = "No internet connection detected."
    alert.addButtonWithTitle("OK")
    alert.show()

    return
}

但是有什么方法可以检查设备是否连接到 VPN? 我正在编写的应用程序需要 VPN 才能访问,因此我不想让用户在未连接到 VPN 时尝试登录,而是想事先提示他们(我认为更好的用户体验)。

谢谢您的帮助。

我使用以下代码使其适用于 Swift 3/4:

private var isConnectedToVpn: Bool {
    if let settings = CFNetworkCopySystemProxySettings()?.takeRetainedValue() as? Dictionary<String, Any>,
        let scopes = settings["__SCOPED__"] as? [String:Any] {
        for (key, _) in scopes {
         if key.contains("tap") || key.contains("tun") || key.contains("ppp") || key.contains("ipsec") {
                return true
            }
        }
    }
    return false
}

我正在使用下面的代码(兼容 Swift 3 和 Swift 4)来检查 iOS 设备上的 VPN 连接,这对我来说工作正常。 在两个私有 VPN 和 ExpressVPN 上进行了测试,均使用 ipsec0 协议。

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" || key == "utun1" || key == "utun2") {
            return true
        }
    }
    return false
}

这里也是代码的要点链接 - Gist Link

对象:

#include <ifaddrs.h>

- (BOOL)isVPNOn
{
    BOOL flag = NO;
    NSString *version = [UIDevice currentDevice].systemVersion;
    // need two ways to judge this.
    if (version.doubleValue >= 9.0)
    {
        NSDictionary *dict = CFBridgingRelease(CFNetworkCopySystemProxySettings());
        NSArray *keys = [dict[@"__SCOPED__"] allKeys];
        for (NSString *key in keys) {
            if ([key rangeOfString:@"tap"].location != NSNotFound ||
                [key rangeOfString:@"tun"].location != NSNotFound ||
                [key rangeOfString:@"ipsec"].location != NSNotFound ||
                [key rangeOfString:@"ppp"].location != NSNotFound){
                flag = YES;
                break;
            }
        }
    }
    else
    {
        struct ifaddrs *interfaces = NULL;
        struct ifaddrs *temp_addr = NULL;
        int success = 0;

        // retrieve the current interfaces - returns 0 on success
        success = getifaddrs(&interfaces);
        if (success == 0)
        {
            // Loop through linked list of interfaces
            temp_addr = interfaces;
            while (temp_addr != NULL)
            {
                NSString *string = [NSString stringWithFormat:@"%s" , temp_addr->ifa_name];
                if ([string rangeOfString:@"tap"].location != NSNotFound ||
                    [string rangeOfString:@"tun"].location != NSNotFound ||
                    [string rangeOfString:@"ipsec"].location != NSNotFound ||
                    [string rangeOfString:@"ppp"].location != NSNotFound)
                {
                    flag = YES;
                    break;
                }
                temp_addr = temp_addr->ifa_next;
            }
        }

        // Free memory
        freeifaddrs(interfaces);
    }

    return flag;
}

参考: RealReachability/RealReachability.m - GitHub

检查是否安装了 VPN(这是较早的答案检测到的)与检查流量是否通过 VPN(或其他代理)路由是有区别的。 如果您只检查是否安装了 VPN,它可能会对安装了仅过滤部分(但不是全部)流量的 3rd 方 VPN 应用程序的用户产生负面影响,这对于企业来说很常见。

下面是一些示例代码,用于检查到特定主机的流量是否通过 VPN/透明代理进行路由。

import Foundation
import Network

func main() {
    
    // Check if connection to host is being routed over transparent proxy (such as VPN) 
    let c = NWConnection(host: "domainname.com", port: 443, using: .tcp)
    c.stateUpdateHandler = { state in
        if (state == .ready) {
            if (c.currentPath?.usesInterfaceType(.other) == true) {
                print("Connection is over transparent proxy")
            } else {
                print("Connection is not over transparent proxy")
            }
        }
    }
    c.start(queue: .main)
    dispatchMain()
}

main()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM