建立VPN连线

时间:2018-10-26 10:54:59

标签: swift macos cocoa vpn

我对macOS开发和敏捷是完全陌生的,所以请忍受...

我正在尝试在Cocoa应用中创建VPN连接。我已将代码基于macosvpn:https://github.com/halo/macosvpn/blob/master/macosvpn/Classes/VPNServiceCreator.swift

这是我到目前为止所拥有的:

    func createVPNService() {
        let options = ["" : ""]
        let prefs = SCPreferencesCreate(nil, "TheVPN" as CFString, nil)

        // These variables will hold references to our new interfaces
        let initialTopInterface: SCNetworkInterface!
        let initialBottomInterface: SCNetworkInterface!

        // L2TP on top of IPv4
        initialBottomInterface = SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4, kSCNetworkInterfaceTypeL2TP)
        // PPP on top of L2TP
        initialTopInterface = SCNetworkInterfaceCreateWithInterface(initialBottomInterface!, kSCNetworkInterfaceTypePPP)

        let service = SCNetworkServiceCreate(prefs!, initialTopInterface!)
        SCNetworkServiceSetName(service!, ("Service Name" as CFString))
        // Because, if we would like to modify the interface, we first need to freshly fetch it from the service
        // See https://lists.apple.com/archives/macnetworkprog/2013/Apr/msg00016.html
        let topInterface = SCNetworkServiceGetInterface(service!)

        SCNetworkInterfaceSetConfiguration(topInterface!, options as CFDictionary)
        // Now let's apply the shared secret to the IPSec part of the L2TP/IPSec Interface
        let thingy:CFString = "IPSec" as CFString
        SCNetworkInterfaceSetExtendedConfiguration(topInterface!, thingy, options as CFDictionary)
        SCNetworkServiceEstablishDefaultConfiguration(service!)
        let networkSet = SCNetworkSetCopyCurrent(prefs!)

        let serviceProtocol = SCNetworkServiceCopyProtocol(service!, kSCNetworkProtocolTypeIPv4)
        SCNetworkProtocolSetConfiguration(serviceProtocol!, options as CFDictionary)
        SCNetworkSetAddService(networkSet!, service!)

        if !SCPreferencesCommitChanges(prefs!) {
            print("Error: Could not commit preferences. (Code \(SCError()))")
        }
        if !SCPreferencesApplyChanges(prefs!) {
            print("Error: Could not apply changes. (Code \(SCError()))")
        }
    }

运行此服务时,未创建任何网络服务。

我不知道真正应该使用哪些选项和偏好?它们现在或多或少是空的。

此外,SCPreferencesCommitChanges和SCPreferencesApplyChanges失败,并带有1003码。我想他们需要root特权才能工作,但我还无法弄清楚如何获得root特权。

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

我终于弄清楚了如何创建VPN连接/服务。但是我仍然必须弄清楚应该如何使用选项和首选项。

SCPreferencesCreate之前被SCPreferencesCreateWithAuthorization和一些授权代码取代。这是更新的代码。

    func createVPNConnection() {
        let flags : AuthorizationFlags = [.interactionAllowed, .extendRights, .preAuthorize]
        var authRef: AuthorizationRef?
        AuthorizationCreate(nil, nil, flags, &authRef)

        let options = ["" : ""]
        let prefs = SCPreferencesCreateWithAuthorization(nil, "TheVPN" as CFString, nil, authRef)
        // These variables will hold references to our new interfaces
        let initialTopInterface: SCNetworkInterface!
        let initialBottomInterface: SCNetworkInterface!

        // L2TP on top of IPv4
        initialBottomInterface = SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4, kSCNetworkInterfaceTypeL2TP)
        // PPP on top of L2TP
        initialTopInterface = SCNetworkInterfaceCreateWithInterface(initialBottomInterface!, kSCNetworkInterfaceTypePPP)

        let service = SCNetworkServiceCreate(prefs!, initialTopInterface!)
        SCNetworkServiceSetName(service!, ("Test Service Name" as CFString))
        // Because, if we would like to modify the interface, we first need to freshly fetch it from the service
        // See https://lists.apple.com/archives/macnetworkprog/2013/Apr/msg00016.html
        let topInterface = SCNetworkServiceGetInterface(service!)

        // Let's apply all configuration to the PPP interface
        // Specifically, the servername, account username and password
        SCNetworkInterfaceSetConfiguration(topInterface!, options as CFDictionary)

        // Now let's apply the shared secret to the IPSec part of the L2TP/IPSec Interface
        let thingy:CFString = "IPSec" as CFString
        SCNetworkInterfaceSetExtendedConfiguration(topInterface!, thingy, options as CFDictionary)
        SCNetworkServiceEstablishDefaultConfiguration(service!)
        let networkSet = SCNetworkSetCopyCurrent(prefs!)
        let serviceProtocol = SCNetworkServiceCopyProtocol(service!, kSCNetworkProtocolTypeIPv4)
        SCNetworkProtocolSetConfiguration(serviceProtocol!, options as CFDictionary)
        SCNetworkSetAddService(networkSet!, service!)

        if !SCPreferencesCommitChanges(prefs!) {
             print("Error: Could not commit preferences. (Code \(SCError()))")
        }
        if !SCPreferencesApplyChanges(prefs!) {
             print("Error: Could not apply changes. (Code \(SCError()))")
        }
    }