diff --git a/CHANGELOG.md b/CHANGELOG.md index 81120b4..23ee1bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Added + +- WireGuard support. [#236](https://github.com/passepartoutvpn/tunnelkit/pull/236) + ## 4.0.3 (2021-11-27) ### Fixed diff --git a/Demo/Demo/Configuration.swift b/Demo/Demo/Configuration.swift index 76acc76..261fea6 100644 --- a/Demo/Demo/Configuration.swift +++ b/Demo/Demo/Configuration.swift @@ -26,9 +26,11 @@ import Foundation import TunnelKitCore import TunnelKitOpenVPN +import TunnelKitWireGuard -struct Configuration { - static let ca = OpenVPN.CryptoContainer(pem: """ +extension OpenVPN { + struct DemoConfiguration { + static let ca = OpenVPN.CryptoContainer(pem: """ -----BEGIN CERTIFICATE----- MIIG6zCCBNOgAwIBAgIJAJhm2PWFkE8NMA0GCSqGSIb3DQEBCwUAMIGpMQswCQYD VQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxEzAR @@ -70,7 +72,7 @@ HiT8esMeX+/orMetzuTPgZInMhznvVdNdfwAfibwlXOKvm154UgDVgnKV405oNM= -----END CERTIFICATE----- """) - static let clientCertificate = OpenVPN.CryptoContainer(pem: """ + static let clientCertificate = OpenVPN.CryptoContainer(pem: """ -----BEGIN CERTIFICATE----- MIIHPTCCBSWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBqTELMAkGA1UEBhMCVVMx CzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKEwpH @@ -114,7 +116,7 @@ kiJ6Ts2iqIvR7T7Eme2vBYH/UJ1DXrdCJx6IDGxxgoXk -----END CERTIFICATE----- """) - static let clientKey = OpenVPN.CryptoContainer(pem: """ + static let clientKey = OpenVPN.CryptoContainer(pem: """ -----BEGIN PRIVATE KEY----- MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDvgpUJoqgvHmbF 2y7Uvt1BfglAXWmzzhaSjr4ZqYLMQncpcwC1iuVgDseGp/rl4C/C64RebIx0hLU1 @@ -169,21 +171,47 @@ M69t86apMrAxkUxVJAWLRBd9fbYyzJgTW61tFqXWTZpiz6bhuWApSEzaHcL3/f5l -----END PRIVATE KEY----- """) - static func make(hostname: String, port: UInt16, socketType: SocketType) -> OpenVPNProvider.Configuration { - var sessionBuilder = OpenVPN.ConfigurationBuilder() - sessionBuilder.ca = ca - sessionBuilder.cipher = .aes128cbc - sessionBuilder.digest = .sha1 - sessionBuilder.compressionFraming = .compLZO - sessionBuilder.renegotiatesAfter = nil - sessionBuilder.hostname = hostname - sessionBuilder.endpointProtocols = [EndpointProtocol(socketType, port)] - sessionBuilder.clientCertificate = clientCertificate - sessionBuilder.clientKey = clientKey - sessionBuilder.mtu = 1350 - var builder = OpenVPNProvider.ConfigurationBuilder(sessionConfiguration: sessionBuilder.build()) - builder.shouldDebug = true - builder.masksPrivateData = false - return builder.build() + static func make(hostname: String, port: UInt16, socketType: SocketType) -> OpenVPNProvider.Configuration { + var sessionBuilder = OpenVPN.ConfigurationBuilder() + sessionBuilder.ca = ca + sessionBuilder.cipher = .aes128cbc + sessionBuilder.digest = .sha1 + sessionBuilder.compressionFraming = .compLZO + sessionBuilder.renegotiatesAfter = nil + sessionBuilder.hostname = hostname + sessionBuilder.endpointProtocols = [EndpointProtocol(socketType, port)] + sessionBuilder.clientCertificate = clientCertificate + sessionBuilder.clientKey = clientKey + sessionBuilder.mtu = 1350 + var builder = OpenVPNProvider.ConfigurationBuilder(sessionConfiguration: sessionBuilder.build()) + builder.shouldDebug = true + builder.masksPrivateData = false + return builder.build() + } + } +} + +extension WireGuard { + struct DemoConfiguration { + static func make( + clientPrivateKey: String, + clientAddress: String, + serverPublicKey: String, + serverAddress: String, + serverPort: String + ) -> WireGuardProvider.Configuration? { + var builder = WireGuard.ConfigurationBuilder() + builder.privateKey = clientPrivateKey + builder.addresses = [clientAddress] + builder.peerPublicKey = serverPublicKey + builder.peerAddress = serverAddress + builder.peerPort = UInt16(serverPort) + builder.allowedIPs = ["0.0.0.0/0"] + builder.dns = ["1.1.1.1", "1.0.0.1"] + guard let cfg = builder.build() else { + return nil + } + return WireGuardProvider.Configuration(innerConfiguration: cfg) + } } } diff --git a/Demo/Demo/DemoTunnel.plist b/Demo/Demo/DemoTunnel.plist index e36f178..c146255 100644 --- a/Demo/Demo/DemoTunnel.plist +++ b/Demo/Demo/DemoTunnel.plist @@ -5,7 +5,7 @@ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName - BasicTunnelExtension + TunnelKitDemoTunnel CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier diff --git a/Demo/Demo/PacketTunnelProvider.swift b/Demo/Demo/OpenVPNPacketTunnelProvider.swift similarity index 96% rename from Demo/Demo/PacketTunnelProvider.swift rename to Demo/Demo/OpenVPNPacketTunnelProvider.swift index b832279..eec46e5 100644 --- a/Demo/Demo/PacketTunnelProvider.swift +++ b/Demo/Demo/OpenVPNPacketTunnelProvider.swift @@ -1,5 +1,5 @@ // -// PacketTunnelProvider.swift +// OpenVPNPacketTunnelProvider.swift // Demo // // Created by Davide De Rosa on 9/15/17. diff --git a/Demo/Demo/WireGuardPacketTunnelProvider.swift b/Demo/Demo/WireGuardPacketTunnelProvider.swift new file mode 100644 index 0000000..770e784 --- /dev/null +++ b/Demo/Demo/WireGuardPacketTunnelProvider.swift @@ -0,0 +1,29 @@ +// +// WireGuardPacketTunnelProvider.swift +// Demo +// +// Created by Davide De Rosa on 11/22/21. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/keeshux +// +// This file is part of TunnelKit. +// +// TunnelKit is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// TunnelKit is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with TunnelKit. If not, see . +// + +import TunnelKitWireGuardAppExtension + +class PacketTunnelProvider: WireGuardTunnelProvider { +} diff --git a/Demo/Demo/iOS/Base.lproj/Main.storyboard b/Demo/Demo/iOS/Base.lproj/Main.storyboard index 4fec762..d5b2052 100644 --- a/Demo/Demo/iOS/Base.lproj/Main.storyboard +++ b/Demo/Demo/iOS/Base.lproj/Main.storyboard @@ -1,16 +1,196 @@ - + - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -20,35 +200,35 @@ - + - + - + - + - + - - + - - - + + - + @@ -114,6 +294,7 @@ + @@ -130,4 +311,12 @@ + + + + + + + + diff --git a/Demo/Demo/iOS/ViewController.swift b/Demo/Demo/iOS/OpenVPNViewController.swift similarity index 93% rename from Demo/Demo/iOS/ViewController.swift rename to Demo/Demo/iOS/OpenVPNViewController.swift index 56a29cb..2813ae7 100644 --- a/Demo/Demo/iOS/ViewController.swift +++ b/Demo/Demo/iOS/OpenVPNViewController.swift @@ -1,5 +1,5 @@ // -// ViewController.swift +// OpenVPNViewController.swift // Demo // // Created by Davide De Rosa on 2/11/17. @@ -25,15 +25,14 @@ import UIKit import TunnelKitCore -import TunnelKitAppExtension import TunnelKitManager import TunnelKitOpenVPN private let appGroup = "group.com.algoritmico.TunnelKit.Demo" -private let tunnelIdentifier = "com.algoritmico.ios.TunnelKit.Demo.Tunnel" +private let tunnelIdentifier = "com.algoritmico.ios.TunnelKit.Demo.OpenVPN.Tunnel" -class ViewController: UIViewController, URLSessionDataDelegate { +class OpenVPNViewController: UIViewController { @IBOutlet var textUsername: UITextField! @IBOutlet var textPassword: UITextField! @@ -97,14 +96,14 @@ class ViewController: UIViewController, URLSessionDataDelegate { let socketType: SocketType = switchTCP.isOn ? .tcp : .udp let credentials = OpenVPN.Credentials(textUsername.text!, textPassword.text!) - let cfg = Configuration.make(hostname: hostname, port: port, socketType: socketType) + let cfg = OpenVPN.DemoConfiguration.make(hostname: hostname, port: port, socketType: socketType) let proto = try! cfg.generatedTunnelProtocol( withBundleIdentifier: tunnelIdentifier, appGroup: appGroup, context: tunnelIdentifier, credentials: credentials ) - let neCfg = NetworkExtensionVPNConfiguration(title: "BasicTunnel", protocolConfiguration: proto, onDemandRules: []) + let neCfg = NetworkExtensionVPNConfiguration(title: "TunnelKit.OpenVPN", protocolConfiguration: proto, onDemandRules: []) vpn.reconnect(configuration: neCfg) { (error) in if let error = error { print("configure error: \(error)") diff --git a/Demo/Demo/iOS/WireGuardViewController.swift b/Demo/Demo/iOS/WireGuardViewController.swift new file mode 100644 index 0000000..d471717 --- /dev/null +++ b/Demo/Demo/iOS/WireGuardViewController.swift @@ -0,0 +1,134 @@ +// +// WireGuardViewController.swift +// Demo +// +// Created by Davide De Rosa on 11/22/21. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/keeshux +// +// This file is part of TunnelKit. +// +// TunnelKit is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// TunnelKit is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with TunnelKit. If not, see . +// + +import UIKit +import TunnelKitManager +import TunnelKitWireGuard +import NetworkExtension + +private let appGroup = "group.com.algoritmico.TunnelKit.Demo" + +private let tunnelIdentifier = "com.algoritmico.ios.TunnelKit.Demo.WireGuard.Tunnel" + +class WireGuardViewController: UIViewController { + @IBOutlet var textClientPrivateKey: UITextField! + + @IBOutlet var textAddress: UITextField! + + @IBOutlet var textServerPublicKey: UITextField! + + @IBOutlet var textServerAddress: UITextField! + + @IBOutlet var textServerPort: UITextField! + + @IBOutlet var buttonConnection: UIButton! + + private let vpn = WireGuardProvider(bundleIdentifier: tunnelIdentifier) + + override func viewDidLoad() { + super.viewDidLoad() + + textClientPrivateKey.placeholder = "client private key" + textAddress.placeholder = "client address" + textServerPublicKey.placeholder = "server public key" + textServerAddress.placeholder = "server address" + textServerPort.placeholder = "server port" + + textAddress.text = "192.168.30.2/32" + + NotificationCenter.default.addObserver( + self, + selector: #selector(VPNStatusDidChange(notification:)), + name: VPN.didChangeStatus, + object: nil + ) + + vpn.prepare(completionHandler: nil) + } + + @IBAction func connectionClicked(_ sender: Any) { + switch vpn.status { + case .disconnected: + connect() + + case .connected, .connecting, .disconnecting: + disconnect() + } + } + + func connect() { + let clientPrivateKey = textClientPrivateKey.text! + let clientAddress = textAddress.text! + let serverPublicKey = textServerPublicKey.text! + let serverAddress = textServerAddress.text! + let serverPort = textServerPort.text! + + guard let cfg = WireGuard.DemoConfiguration.make( + clientPrivateKey: clientPrivateKey, + clientAddress: clientAddress, + serverPublicKey: serverPublicKey, + serverAddress: serverAddress, + serverPort: serverPort + ) else { + print("Configuration incomplete") + return + } + let proto = try! cfg.generatedTunnelProtocol( + withBundleIdentifier: tunnelIdentifier, + appGroup: appGroup, + context: tunnelIdentifier + ) + + let neCfg = NetworkExtensionVPNConfiguration(title: "TunnelKit.WireGuard", protocolConfiguration: proto, onDemandRules: []) + vpn.reconnect(configuration: neCfg) { (error) in + if let error = error { + print("configure error: \(error)") + return + } + } + } + + func disconnect() { + vpn.disconnect(completionHandler: nil) + } + + func updateButton() { + switch vpn.status { + case .connected, .connecting: + buttonConnection.setTitle("Disconnect", for: .normal) + + case .disconnected: + buttonConnection.setTitle("Connect", for: .normal) + + case .disconnecting: + buttonConnection.setTitle("Disconnecting", for: .normal) + } + } + + @objc private func VPNStatusDidChange(notification: NSNotification) { + print("VPNStatusDidChange: \(vpn.status)") + updateButton() + } +} diff --git a/Demo/Demo/macOS/Base.lproj/Main.storyboard b/Demo/Demo/macOS/Base.lproj/Main.storyboard index 1822950..6d45cc8 100644 --- a/Demo/Demo/macOS/Base.lproj/Main.storyboard +++ b/Demo/Demo/macOS/Base.lproj/Main.storyboard @@ -1,8 +1,8 @@ - + - + @@ -12,11 +12,11 @@ - + - + - + @@ -30,7 +30,7 @@ - + @@ -48,7 +48,7 @@ - + @@ -661,7 +661,7 @@ - + @@ -675,17 +675,17 @@ - + - + - + @@ -695,17 +695,150 @@ - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -798,7 +931,7 @@ - + diff --git a/Demo/Demo/macOS/DemoTunnel.entitlements b/Demo/Demo/macOS/DemoTunnel.entitlements index 7336b16..f2940f3 100644 --- a/Demo/Demo/macOS/DemoTunnel.entitlements +++ b/Demo/Demo/macOS/DemoTunnel.entitlements @@ -14,6 +14,8 @@ com.apple.security.network.client + com.apple.security.network.server + keychain-access-groups $(AppIdentifierPrefix)group.com.algoritmico.TunnelKit.Demo diff --git a/Demo/Demo/macOS/ViewController.swift b/Demo/Demo/macOS/OpenVPNViewController.swift similarity index 92% rename from Demo/Demo/macOS/ViewController.swift rename to Demo/Demo/macOS/OpenVPNViewController.swift index 859d6b7..72d6322 100644 --- a/Demo/Demo/macOS/ViewController.swift +++ b/Demo/Demo/macOS/OpenVPNViewController.swift @@ -1,5 +1,5 @@ // -// ViewController.swift +// OpenVPNViewController.swift // Demo // // Created by Davide De Rosa on 10/15/17. @@ -25,15 +25,14 @@ import Cocoa import TunnelKitCore -import TunnelKitAppExtension import TunnelKitManager import TunnelKitOpenVPN private let appGroup = "DTDYD63ZX9.group.com.algoritmico.TunnelKit.Demo" -private let tunnelIdentifier = "com.algoritmico.macos.TunnelKit.Demo.Tunnel" +private let tunnelIdentifier = "com.algoritmico.macos.TunnelKit.Demo.OpenVPN.Tunnel" -class ViewController: NSViewController { +class OpenVPNViewController: NSViewController { @IBOutlet var textUsername: NSTextField! @IBOutlet var textPassword: NSTextField! @@ -88,14 +87,14 @@ class ViewController: NSViewController { let port = UInt16(textPort.stringValue)! let credentials = OpenVPN.Credentials(textUsername.stringValue, textPassword.stringValue) - let cfg = Configuration.make(hostname: hostname, port: port, socketType: .udp) + let cfg = OpenVPN.DemoConfiguration.make(hostname: hostname, port: port, socketType: .udp) let proto = try! cfg.generatedTunnelProtocol( withBundleIdentifier: tunnelIdentifier, appGroup: appGroup, context: tunnelIdentifier, credentials: credentials ) - let neCfg = NetworkExtensionVPNConfiguration(title: "BasicTunnel", protocolConfiguration: proto, onDemandRules: []) + let neCfg = NetworkExtensionVPNConfiguration(title: "TunnelKit.OpenVPN", protocolConfiguration: proto, onDemandRules: []) vpn.reconnect(configuration: neCfg) { (error) in if let error = error { print("configure error: \(error)") diff --git a/Demo/Demo/macOS/WireGuardViewController.swift b/Demo/Demo/macOS/WireGuardViewController.swift new file mode 100644 index 0000000..9564793 --- /dev/null +++ b/Demo/Demo/macOS/WireGuardViewController.swift @@ -0,0 +1,134 @@ +// +// WireGuardViewController.swift +// Demo +// +// Created by Davide De Rosa on 11/22/21. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/keeshux +// +// This file is part of TunnelKit. +// +// TunnelKit is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// TunnelKit is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with TunnelKit. If not, see . +// + +import Cocoa +import TunnelKitManager +import TunnelKitWireGuard +import NetworkExtension + +private let appGroup = "DTDYD63ZX9.group.com.algoritmico.TunnelKit.Demo" + +private let tunnelIdentifier = "com.algoritmico.macos.TunnelKit.Demo.WireGuard.Tunnel" + +class WireGuardViewController: NSViewController { + @IBOutlet var textClientPrivateKey: NSTextField! + + @IBOutlet var textAddress: NSTextField! + + @IBOutlet var textServerPublicKey: NSTextField! + + @IBOutlet var textServerAddress: NSTextField! + + @IBOutlet var textServerPort: NSTextField! + + @IBOutlet var buttonConnection: NSButton! + + private let vpn = WireGuardProvider(bundleIdentifier: tunnelIdentifier) + + override func viewDidLoad() { + super.viewDidLoad() + + textClientPrivateKey.placeholderString = "client private key" + textAddress.placeholderString = "client address" + textServerPublicKey.placeholderString = "server public key" + textServerAddress.placeholderString = "server address" + textServerPort.placeholderString = "server port" + + textAddress.stringValue = "192.168.30.2/32" + + NotificationCenter.default.addObserver( + self, + selector: #selector(VPNStatusDidChange(notification:)), + name: VPN.didChangeStatus, + object: nil + ) + + vpn.prepare(completionHandler: nil) + } + + @IBAction func connectionClicked(_ sender: Any) { + switch vpn.status { + case .disconnected: + connect() + + case .connected, .connecting, .disconnecting: + disconnect() + } + } + + func connect() { + let clientPrivateKey = textClientPrivateKey.stringValue + let clientAddress = textAddress.stringValue + let serverPublicKey = textServerPublicKey.stringValue + let serverAddress = textServerAddress.stringValue + let serverPort = textServerPort.stringValue + + guard let cfg = WireGuard.DemoConfiguration.make( + clientPrivateKey: clientPrivateKey, + clientAddress: clientAddress, + serverPublicKey: serverPublicKey, + serverAddress: serverAddress, + serverPort: serverPort + ) else { + print("Configuration incomplete") + return + } + let proto = try! cfg.generatedTunnelProtocol( + withBundleIdentifier: tunnelIdentifier, + appGroup: appGroup, + context: tunnelIdentifier + ) + + let neCfg = NetworkExtensionVPNConfiguration(title: "TunnelKit.WireGuard", protocolConfiguration: proto, onDemandRules: []) + vpn.reconnect(configuration: neCfg) { (error) in + if let error = error { + print("configure error: \(error)") + return + } + } + } + + func disconnect() { + vpn.disconnect(completionHandler: nil) + } + + func updateButton() { + switch vpn.status { + case .connected, .connecting: + buttonConnection.title = "Disconnect" + + case .disconnected: + buttonConnection.title = "Connect" + + case .disconnecting: + buttonConnection.title = "Disconnecting" + } + } + + @objc private func VPNStatusDidChange(notification: NSNotification) { + print("VPNStatusDidChange: \(vpn.status)") + updateButton() + } +} diff --git a/Demo/TunnelKit.xcodeproj/project.pbxproj b/Demo/TunnelKit.xcodeproj/project.pbxproj index a51f439..64766fc 100644 --- a/Demo/TunnelKit.xcodeproj/project.pbxproj +++ b/Demo/TunnelKit.xcodeproj/project.pbxproj @@ -8,22 +8,22 @@ /* Begin PBXBuildFile section */ 0E05418725A2334500EFC5FF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E05414B25A231D500EFC5FF /* AppDelegate.swift */; }; - 0E05418825A2334500EFC5FF /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E05414425A231D500EFC5FF /* ViewController.swift */; }; + 0E05418825A2334500EFC5FF /* OpenVPNViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E05414425A231D500EFC5FF /* OpenVPNViewController.swift */; }; 0E05418925A2334500EFC5FF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E05414525A231D500EFC5FF /* Assets.xcassets */; }; 0E05418A25A2334900EFC5FF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0E05414825A231D500EFC5FF /* Main.storyboard */; }; 0E05418B25A2334900EFC5FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0E05414625A231D500EFC5FF /* LaunchScreen.storyboard */; }; 0E0541A125A2343500EFC5FF /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E0541A025A2343500EFC5FF /* NetworkExtension.framework */; }; - 0E0541A925A2343500EFC5FF /* TunnelKitDemoTunnel-iOS.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 0E05419F25A2343500EFC5FF /* TunnelKitDemoTunnel-iOS.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - 0E0541D125A2354500EFC5FF /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E05413825A231D500EFC5FF /* PacketTunnelProvider.swift */; }; + 0E0541A925A2343500EFC5FF /* TunnelKitDemoOpenVPNTunnel-iOS.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 0E05419F25A2343500EFC5FF /* TunnelKitDemoOpenVPNTunnel-iOS.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 0E0541D125A2354500EFC5FF /* OpenVPNPacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E05413825A231D500EFC5FF /* OpenVPNPacketTunnelProvider.swift */; }; 0E0541D825A2355000EFC5FF /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E05413425A231D500EFC5FF /* Configuration.swift */; }; 0E05425825A2392E00EFC5FF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E05414125A231D500EFC5FF /* AppDelegate.swift */; }; - 0E05425925A2392E00EFC5FF /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E05413C25A231D500EFC5FF /* ViewController.swift */; }; + 0E05425925A2392E00EFC5FF /* OpenVPNViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E05413C25A231D500EFC5FF /* OpenVPNViewController.swift */; }; 0E05426125A2393300EFC5FF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E05413D25A231D500EFC5FF /* Assets.xcassets */; }; 0E05426925A2393B00EFC5FF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0E05413E25A231D500EFC5FF /* Main.storyboard */; }; 0E05427825A239C600EFC5FF /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E0541A025A2343500EFC5FF /* NetworkExtension.framework */; }; - 0E05428025A239C600EFC5FF /* TunnelKitDemoTunnel-macOS.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 0E05427725A239C600EFC5FF /* TunnelKitDemoTunnel-macOS.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 0E05428025A239C600EFC5FF /* TunnelKitDemoOpenVPNTunnel-macOS.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 0E05427725A239C600EFC5FF /* TunnelKitDemoOpenVPNTunnel-macOS.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 0E0542B925A23A8100EFC5FF /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E05413425A231D500EFC5FF /* Configuration.swift */; }; - 0E0542C225A23A8400EFC5FF /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E05413825A231D500EFC5FF /* PacketTunnelProvider.swift */; }; + 0E0542C225A23A8400EFC5FF /* OpenVPNPacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E05413825A231D500EFC5FF /* OpenVPNPacketTunnelProvider.swift */; }; 0E1108AC1F77B9F900A92462 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E1108AB1F77B9F900A92462 /* AppDelegate.swift */; }; 0E1108AE1F77B9F900A92462 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E1108AD1F77B9F900A92462 /* ViewController.swift */; }; 0E1108B11F77B9F900A92462 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0E1108AF1F77B9F900A92462 /* Main.storyboard */; }; @@ -31,6 +31,18 @@ 0E1108B61F77B9F900A92462 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0E1108B41F77B9F900A92462 /* LaunchScreen.storyboard */; }; 0E80FA5127396F5F000F5A45 /* TunnelKitOpenVPNAppExtension in Frameworks */ = {isa = PBXBuildFile; productRef = 0E80FA5027396F5F000F5A45 /* TunnelKitOpenVPNAppExtension */; }; 0E80FA5327396F66000F5A45 /* TunnelKitOpenVPNAppExtension in Frameworks */ = {isa = PBXBuildFile; productRef = 0E80FA5227396F66000F5A45 /* TunnelKitOpenVPNAppExtension */; }; + 0E81EB4C274BACF200E5F2D3 /* WireGuardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E81EB4B274BACF200E5F2D3 /* WireGuardViewController.swift */; }; + 0E81EB4F274BAE0A00E5F2D3 /* WireGuardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E81EB4D274BAE0400E5F2D3 /* WireGuardViewController.swift */; }; + 0E81EB51274BB02100E5F2D3 /* TunnelKitWireGuard in Frameworks */ = {isa = PBXBuildFile; productRef = 0E81EB50274BB02100E5F2D3 /* TunnelKitWireGuard */; }; + 0E81EB53274BB02600E5F2D3 /* TunnelKitWireGuard in Frameworks */ = {isa = PBXBuildFile; productRef = 0E81EB52274BB02600E5F2D3 /* TunnelKitWireGuard */; }; + 0E833A85274BC39C008EA397 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E0541A025A2343500EFC5FF /* NetworkExtension.framework */; }; + 0E833A96274BC3B1008EA397 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E0541A025A2343500EFC5FF /* NetworkExtension.framework */; }; + 0E833AA3274BC480008EA397 /* TunnelKitWireGuardAppExtension in Frameworks */ = {isa = PBXBuildFile; productRef = 0E833AA2274BC480008EA397 /* TunnelKitWireGuardAppExtension */; }; + 0E833AA5274BC484008EA397 /* TunnelKitWireGuardAppExtension in Frameworks */ = {isa = PBXBuildFile; productRef = 0E833AA4274BC484008EA397 /* TunnelKitWireGuardAppExtension */; }; + 0E833AAA274BC5BA008EA397 /* TunnelKitDemoWireGuardTunnel-macOS.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 0E833A95274BC3B1008EA397 /* TunnelKitDemoWireGuardTunnel-macOS.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 0E833AAB274BC5C2008EA397 /* TunnelKitDemoWireGuardTunnel-iOS.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 0E833A84274BC39C008EA397 /* TunnelKitDemoWireGuardTunnel-iOS.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 0E833AAD274BC64F008EA397 /* WireGuardPacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E833AAC274BC64F008EA397 /* WireGuardPacketTunnelProvider.swift */; }; + 0E833AAE274BC64F008EA397 /* WireGuardPacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E833AAC274BC64F008EA397 /* WireGuardPacketTunnelProvider.swift */; }; 0EFD5B312727250500C7D5FD /* TunnelKitOpenVPN in Frameworks */ = {isa = PBXBuildFile; productRef = 0EFD5B302727250500C7D5FD /* TunnelKitOpenVPN */; }; 0EFD5B332727250B00C7D5FD /* TunnelKitOpenVPN in Frameworks */ = {isa = PBXBuildFile; productRef = 0EFD5B322727250B00C7D5FD /* TunnelKitOpenVPN */; }; /* End PBXBuildFile section */ @@ -50,6 +62,34 @@ remoteGlobalIDString = 0E05427625A239C600EFC5FF; remoteInfo = Tunnel; }; + 0E833A8B274BC39C008EA397 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0E17D7F01F730D9F009EE129 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0E833A83274BC39C008EA397; + remoteInfo = "TunnelKitDemoWireGuardTunnel-iOS"; + }; + 0E833A9C274BC3B1008EA397 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0E17D7F01F730D9F009EE129 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0E833A94274BC3B1008EA397; + remoteInfo = "TunnelKitDemoWireGuardTunnel-macOS"; + }; + 0E833AA6274BC496008EA397 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0E17D7F01F730D9F009EE129 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0E81EB54274BB0D000E5F2D3; + remoteInfo = "TunnelKitDemoWireGuardKitGo-macOS"; + }; + 0E833AA8274BC49B008EA397 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0E17D7F01F730D9F009EE129 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0EDD211D274BB4CF006833D1; + remoteInfo = "TunnelKitDemoWireGuardKitGo-iOS"; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -59,7 +99,8 @@ dstPath = ""; dstSubfolderSpec = 13; files = ( - 0E0541A925A2343500EFC5FF /* TunnelKitDemoTunnel-iOS.appex in Embed App Extensions */, + 0E833AAB274BC5C2008EA397 /* TunnelKitDemoWireGuardTunnel-iOS.appex in Embed App Extensions */, + 0E0541A925A2343500EFC5FF /* TunnelKitDemoOpenVPNTunnel-iOS.appex in Embed App Extensions */, ); name = "Embed App Extensions"; runOnlyForDeploymentPostprocessing = 0; @@ -70,7 +111,8 @@ dstPath = ""; dstSubfolderSpec = 13; files = ( - 0E05428025A239C600EFC5FF /* TunnelKitDemoTunnel-macOS.appex in Embed App Extensions */, + 0E833AAA274BC5BA008EA397 /* TunnelKitDemoWireGuardTunnel-macOS.appex in Embed App Extensions */, + 0E05428025A239C600EFC5FF /* TunnelKitDemoOpenVPNTunnel-macOS.appex in Embed App Extensions */, ); name = "Embed App Extensions"; runOnlyForDeploymentPostprocessing = 0; @@ -111,15 +153,15 @@ 0E05413025A231D500EFC5FF /* DemoTunnel.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DemoTunnel.entitlements; sourceTree = ""; }; 0E05413225A231D500EFC5FF /* DemoTunnel.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = DemoTunnel.plist; sourceTree = ""; }; 0E05413425A231D500EFC5FF /* Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = ""; }; - 0E05413825A231D500EFC5FF /* PacketTunnelProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PacketTunnelProvider.swift; sourceTree = ""; }; + 0E05413825A231D500EFC5FF /* OpenVPNPacketTunnelProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenVPNPacketTunnelProvider.swift; sourceTree = ""; }; 0E05413925A231D500EFC5FF /* DemoTunnel.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DemoTunnel.entitlements; sourceTree = ""; }; - 0E05413C25A231D500EFC5FF /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 0E05413C25A231D500EFC5FF /* OpenVPNViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenVPNViewController.swift; sourceTree = ""; }; 0E05413D25A231D500EFC5FF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 0E05413F25A231D500EFC5FF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 0E05414025A231D500EFC5FF /* Demo.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Demo.entitlements; sourceTree = ""; }; 0E05414125A231D500EFC5FF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 0E05414225A231D500EFC5FF /* Demo.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Demo.plist; sourceTree = ""; }; - 0E05414425A231D500EFC5FF /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 0E05414425A231D500EFC5FF /* OpenVPNViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenVPNViewController.swift; sourceTree = ""; }; 0E05414525A231D500EFC5FF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 0E05414725A231D500EFC5FF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 0E05414925A231D500EFC5FF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; @@ -127,10 +169,10 @@ 0E05414B25A231D500EFC5FF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 0E05414C25A231D500EFC5FF /* Demo.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Demo.plist; sourceTree = ""; }; 0E05416925A232FD00EFC5FF /* TunnelKitDemo-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "TunnelKitDemo-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - 0E05419F25A2343500EFC5FF /* TunnelKitDemoTunnel-iOS.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "TunnelKitDemoTunnel-iOS.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; + 0E05419F25A2343500EFC5FF /* TunnelKitDemoOpenVPNTunnel-iOS.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "TunnelKitDemoOpenVPNTunnel-iOS.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 0E0541A025A2343500EFC5FF /* NetworkExtension.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NetworkExtension.framework; path = System/Library/Frameworks/NetworkExtension.framework; sourceTree = SDKROOT; }; 0E05422C25A236EB00EFC5FF /* TunnelKitDemo-macOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "TunnelKitDemo-macOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - 0E05427725A239C600EFC5FF /* TunnelKitDemoTunnel-macOS.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "TunnelKitDemoTunnel-macOS.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; + 0E05427725A239C600EFC5FF /* TunnelKitDemoOpenVPNTunnel-macOS.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "TunnelKitDemoOpenVPNTunnel-macOS.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 0E1108A91F77B9F900A92462 /* TunnelKitHost.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TunnelKitHost.app; sourceTree = BUILT_PRODUCTS_DIR; }; 0E1108AB1F77B9F900A92462 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 0E1108AD1F77B9F900A92462 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; @@ -141,6 +183,11 @@ 0E26B05627272767008FB1E7 /* tunnelkit */ = {isa = PBXFileReference; lastKnownFileType = folder; name = tunnelkit; path = ..; sourceTree = ""; }; 0E411B9F2271FA3300E0852C /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libresolv.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/lib/libresolv.tbd; sourceTree = DEVELOPER_DIR; }; 0E411BA12271FA3C00E0852C /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libresolv.tbd; path = usr/lib/libresolv.tbd; sourceTree = SDKROOT; }; + 0E81EB4B274BACF200E5F2D3 /* WireGuardViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WireGuardViewController.swift; sourceTree = ""; }; + 0E81EB4D274BAE0400E5F2D3 /* WireGuardViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WireGuardViewController.swift; sourceTree = ""; }; + 0E833A84274BC39C008EA397 /* TunnelKitDemoWireGuardTunnel-iOS.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "TunnelKitDemoWireGuardTunnel-iOS.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; + 0E833A95274BC3B1008EA397 /* TunnelKitDemoWireGuardTunnel-macOS.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "TunnelKitDemoWireGuardTunnel-macOS.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; + 0E833AAC274BC64F008EA397 /* WireGuardPacketTunnelProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WireGuardPacketTunnelProvider.swift; sourceTree = ""; }; 0E85A25B202CCA3D0059E9F9 /* Host.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Host.entitlements; sourceTree = ""; }; 44612F27B9EF890AF8B926DB /* Pods_ios_TunnelKit_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ios_TunnelKit_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 488FA71CA2DC38D2FDF7D1D8 /* Pods_ios_TunnelKitDemoTunnel_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ios_TunnelKitDemoTunnel_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -158,6 +205,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0E81EB53274BB02600E5F2D3 /* TunnelKitWireGuard in Frameworks */, 0EFD5B332727250B00C7D5FD /* TunnelKitOpenVPN in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -166,8 +214,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 0E0541A125A2343500EFC5FF /* NetworkExtension.framework in Frameworks */, 0E80FA5127396F5F000F5A45 /* TunnelKitOpenVPNAppExtension in Frameworks */, + 0E0541A125A2343500EFC5FF /* NetworkExtension.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -175,6 +223,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0E81EB51274BB02100E5F2D3 /* TunnelKitWireGuard in Frameworks */, 0EFD5B312727250500C7D5FD /* TunnelKitOpenVPN in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -195,6 +244,24 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 0E833A81274BC39C008EA397 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E833AA3274BC480008EA397 /* TunnelKitWireGuardAppExtension in Frameworks */, + 0E833A85274BC39C008EA397 /* NetworkExtension.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0E833A92274BC3B1008EA397 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E833AA5274BC484008EA397 /* TunnelKitWireGuardAppExtension in Frameworks */, + 0E833A96274BC3B1008EA397 /* NetworkExtension.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -205,7 +272,8 @@ 0E05413B25A231D500EFC5FF /* macOS */, 0E05413225A231D500EFC5FF /* DemoTunnel.plist */, 0E05413425A231D500EFC5FF /* Configuration.swift */, - 0E05413825A231D500EFC5FF /* PacketTunnelProvider.swift */, + 0E05413825A231D500EFC5FF /* OpenVPNPacketTunnelProvider.swift */, + 0E833AAC274BC64F008EA397 /* WireGuardPacketTunnelProvider.swift */, ); path = Demo; sourceTree = ""; @@ -217,7 +285,8 @@ 0E05413025A231D500EFC5FF /* DemoTunnel.entitlements */, 0E05414225A231D500EFC5FF /* Demo.plist */, 0E05414125A231D500EFC5FF /* AppDelegate.swift */, - 0E05413C25A231D500EFC5FF /* ViewController.swift */, + 0E05413C25A231D500EFC5FF /* OpenVPNViewController.swift */, + 0E81EB4D274BAE0400E5F2D3 /* WireGuardViewController.swift */, 0E05413D25A231D500EFC5FF /* Assets.xcassets */, 0E05413E25A231D500EFC5FF /* Main.storyboard */, ); @@ -231,7 +300,8 @@ 0E05413925A231D500EFC5FF /* DemoTunnel.entitlements */, 0E05414C25A231D500EFC5FF /* Demo.plist */, 0E05414B25A231D500EFC5FF /* AppDelegate.swift */, - 0E05414425A231D500EFC5FF /* ViewController.swift */, + 0E05414425A231D500EFC5FF /* OpenVPNViewController.swift */, + 0E81EB4B274BACF200E5F2D3 /* WireGuardViewController.swift */, 0E05414525A231D500EFC5FF /* Assets.xcassets */, 0E05414625A231D500EFC5FF /* LaunchScreen.storyboard */, 0E05414825A231D500EFC5FF /* Main.storyboard */, @@ -269,9 +339,11 @@ children = ( 0E1108A91F77B9F900A92462 /* TunnelKitHost.app */, 0E05416925A232FD00EFC5FF /* TunnelKitDemo-iOS.app */, - 0E05419F25A2343500EFC5FF /* TunnelKitDemoTunnel-iOS.appex */, + 0E05419F25A2343500EFC5FF /* TunnelKitDemoOpenVPNTunnel-iOS.appex */, 0E05422C25A236EB00EFC5FF /* TunnelKitDemo-macOS.app */, - 0E05427725A239C600EFC5FF /* TunnelKitDemoTunnel-macOS.appex */, + 0E05427725A239C600EFC5FF /* TunnelKitDemoOpenVPNTunnel-macOS.appex */, + 0E833A84274BC39C008EA397 /* TunnelKitDemoWireGuardTunnel-iOS.appex */, + 0E833A95274BC3B1008EA397 /* TunnelKitDemoWireGuardTunnel-macOS.appex */, ); name = Products; sourceTree = ""; @@ -305,6 +377,37 @@ }; /* End PBXGroup section */ +/* Begin PBXLegacyTarget section */ + 0E81EB54274BB0D000E5F2D3 /* TunnelKitDemoWireGuardKitGo-macOS */ = { + isa = PBXLegacyTarget; + buildArgumentsString = "$(ACTION)"; + buildConfigurationList = 0E81EB55274BB0D000E5F2D3 /* Build configuration list for PBXLegacyTarget "TunnelKitDemoWireGuardKitGo-macOS" */; + buildPhases = ( + ); + buildToolPath = "$(PROJECT_DIR)/../Scripts/build_wireguard_go_bridge.sh"; + buildWorkingDirectory = ""; + dependencies = ( + ); + name = "TunnelKitDemoWireGuardKitGo-macOS"; + passBuildSettingsInEnvironment = 1; + productName = "TunnelKitDemoWireGuardKitGo-macOS"; + }; + 0EDD211D274BB4CF006833D1 /* TunnelKitDemoWireGuardKitGo-iOS */ = { + isa = PBXLegacyTarget; + buildArgumentsString = "$(ACTION)"; + buildConfigurationList = 0EDD211E274BB4CF006833D1 /* Build configuration list for PBXLegacyTarget "TunnelKitDemoWireGuardKitGo-iOS" */; + buildPhases = ( + ); + buildToolPath = "$(PROJECT_DIR)/../Scripts/build_wireguard_go_bridge.sh"; + buildWorkingDirectory = ""; + dependencies = ( + ); + name = "TunnelKitDemoWireGuardKitGo-iOS"; + passBuildSettingsInEnvironment = 1; + productName = "TunnelKitDemoWireGuardKitGo-iOS"; + }; +/* End PBXLegacyTarget section */ + /* Begin PBXNativeTarget section */ 0E05416825A232FD00EFC5FF /* TunnelKitDemo-iOS */ = { isa = PBXNativeTarget; @@ -320,18 +423,20 @@ ); dependencies = ( 0E0541A825A2343500EFC5FF /* PBXTargetDependency */, + 0E833A8C274BC39C008EA397 /* PBXTargetDependency */, ); name = "TunnelKitDemo-iOS"; packageProductDependencies = ( 0EFD5B322727250B00C7D5FD /* TunnelKitOpenVPN */, + 0E81EB52274BB02600E5F2D3 /* TunnelKitWireGuard */, ); productName = Demo; productReference = 0E05416925A232FD00EFC5FF /* TunnelKitDemo-iOS.app */; productType = "com.apple.product-type.application"; }; - 0E05419E25A2343500EFC5FF /* TunnelKitDemoTunnel-iOS */ = { + 0E05419E25A2343500EFC5FF /* TunnelKitDemoOpenVPNTunnel-iOS */ = { isa = PBXNativeTarget; - buildConfigurationList = 0E0541AA25A2343500EFC5FF /* Build configuration list for PBXNativeTarget "TunnelKitDemoTunnel-iOS" */; + buildConfigurationList = 0E0541AA25A2343500EFC5FF /* Build configuration list for PBXNativeTarget "TunnelKitDemoOpenVPNTunnel-iOS" */; buildPhases = ( 0E05419B25A2343500EFC5FF /* Sources */, 0E05419C25A2343500EFC5FF /* Frameworks */, @@ -341,12 +446,12 @@ ); dependencies = ( ); - name = "TunnelKitDemoTunnel-iOS"; + name = "TunnelKitDemoOpenVPNTunnel-iOS"; packageProductDependencies = ( 0E80FA5027396F5F000F5A45 /* TunnelKitOpenVPNAppExtension */, ); productName = Tunnel; - productReference = 0E05419F25A2343500EFC5FF /* TunnelKitDemoTunnel-iOS.appex */; + productReference = 0E05419F25A2343500EFC5FF /* TunnelKitDemoOpenVPNTunnel-iOS.appex */; productType = "com.apple.product-type.app-extension"; }; 0E05422B25A236EB00EFC5FF /* TunnelKitDemo-macOS */ = { @@ -363,18 +468,20 @@ ); dependencies = ( 0E05427F25A239C600EFC5FF /* PBXTargetDependency */, + 0E833A9D274BC3B1008EA397 /* PBXTargetDependency */, ); name = "TunnelKitDemo-macOS"; packageProductDependencies = ( 0EFD5B302727250500C7D5FD /* TunnelKitOpenVPN */, + 0E81EB50274BB02100E5F2D3 /* TunnelKitWireGuard */, ); productName = Demo; productReference = 0E05422C25A236EB00EFC5FF /* TunnelKitDemo-macOS.app */; productType = "com.apple.product-type.application"; }; - 0E05427625A239C600EFC5FF /* TunnelKitDemoTunnel-macOS */ = { + 0E05427625A239C600EFC5FF /* TunnelKitDemoOpenVPNTunnel-macOS */ = { isa = PBXNativeTarget; - buildConfigurationList = 0E05428125A239C600EFC5FF /* Build configuration list for PBXNativeTarget "TunnelKitDemoTunnel-macOS" */; + buildConfigurationList = 0E05428125A239C600EFC5FF /* Build configuration list for PBXNativeTarget "TunnelKitDemoOpenVPNTunnel-macOS" */; buildPhases = ( 0E05427325A239C600EFC5FF /* Sources */, 0E05427425A239C600EFC5FF /* Frameworks */, @@ -384,12 +491,12 @@ ); dependencies = ( ); - name = "TunnelKitDemoTunnel-macOS"; + name = "TunnelKitDemoOpenVPNTunnel-macOS"; packageProductDependencies = ( 0E80FA5227396F66000F5A45 /* TunnelKitOpenVPNAppExtension */, ); productName = Tunnel; - productReference = 0E05427725A239C600EFC5FF /* TunnelKitDemoTunnel-macOS.appex */; + productReference = 0E05427725A239C600EFC5FF /* TunnelKitDemoOpenVPNTunnel-macOS.appex */; productType = "com.apple.product-type.app-extension"; }; 0E1108A81F77B9F900A92462 /* TunnelKitHost */ = { @@ -410,13 +517,55 @@ productReference = 0E1108A91F77B9F900A92462 /* TunnelKitHost.app */; productType = "com.apple.product-type.application"; }; + 0E833A83274BC39C008EA397 /* TunnelKitDemoWireGuardTunnel-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0E833A8E274BC39C008EA397 /* Build configuration list for PBXNativeTarget "TunnelKitDemoWireGuardTunnel-iOS" */; + buildPhases = ( + 0E833A80274BC39C008EA397 /* Sources */, + 0E833A81274BC39C008EA397 /* Frameworks */, + 0E833A82274BC39C008EA397 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 0E833AA9274BC49B008EA397 /* PBXTargetDependency */, + ); + name = "TunnelKitDemoWireGuardTunnel-iOS"; + packageProductDependencies = ( + 0E833AA2274BC480008EA397 /* TunnelKitWireGuardAppExtension */, + ); + productName = "TunnelKitDemoWireGuardTunnel-iOS"; + productReference = 0E833A84274BC39C008EA397 /* TunnelKitDemoWireGuardTunnel-iOS.appex */; + productType = "com.apple.product-type.app-extension"; + }; + 0E833A94274BC3B1008EA397 /* TunnelKitDemoWireGuardTunnel-macOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0E833A9F274BC3B2008EA397 /* Build configuration list for PBXNativeTarget "TunnelKitDemoWireGuardTunnel-macOS" */; + buildPhases = ( + 0E833A91274BC3B1008EA397 /* Sources */, + 0E833A92274BC3B1008EA397 /* Frameworks */, + 0E833A93274BC3B1008EA397 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 0E833AA7274BC496008EA397 /* PBXTargetDependency */, + ); + name = "TunnelKitDemoWireGuardTunnel-macOS"; + packageProductDependencies = ( + 0E833AA4274BC484008EA397 /* TunnelKitWireGuardAppExtension */, + ); + productName = "TunnelKitDemoWireGuardTunnel-macOS"; + productReference = 0E833A95274BC3B1008EA397 /* TunnelKitDemoWireGuardTunnel-macOS.appex */; + productType = "com.apple.product-type.app-extension"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 0E17D7F01F730D9F009EE129 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1230; + LastSwiftUpdateCheck = 1310; LastUpgradeCheck = 1230; ORGANIZATIONNAME = "Davide De Rosa"; TargetAttributes = { @@ -449,6 +598,20 @@ }; }; }; + 0E81EB54274BB0D000E5F2D3 = { + CreatedOnToolsVersion = 13.1; + }; + 0E833A83274BC39C008EA397 = { + CreatedOnToolsVersion = 13.1; + LastSwiftMigration = 1310; + }; + 0E833A94274BC3B1008EA397 = { + CreatedOnToolsVersion = 13.1; + LastSwiftMigration = 1310; + }; + 0EDD211D274BB4CF006833D1 = { + CreatedOnToolsVersion = 13.1; + }; }; }; buildConfigurationList = 0E17D7F31F730D9F009EE129 /* Build configuration list for PBXProject "TunnelKit" */; @@ -467,8 +630,12 @@ 0E1108A81F77B9F900A92462 /* TunnelKitHost */, 0E05416825A232FD00EFC5FF /* TunnelKitDemo-iOS */, 0E05422B25A236EB00EFC5FF /* TunnelKitDemo-macOS */, - 0E05419E25A2343500EFC5FF /* TunnelKitDemoTunnel-iOS */, - 0E05427625A239C600EFC5FF /* TunnelKitDemoTunnel-macOS */, + 0E05419E25A2343500EFC5FF /* TunnelKitDemoOpenVPNTunnel-iOS */, + 0E05427625A239C600EFC5FF /* TunnelKitDemoOpenVPNTunnel-macOS */, + 0E833A83274BC39C008EA397 /* TunnelKitDemoWireGuardTunnel-iOS */, + 0E833A94274BC3B1008EA397 /* TunnelKitDemoWireGuardTunnel-macOS */, + 0EDD211D274BB4CF006833D1 /* TunnelKitDemoWireGuardKitGo-iOS */, + 0E81EB54274BB0D000E5F2D3 /* TunnelKitDemoWireGuardKitGo-macOS */, ); }; /* End PBXProject section */ @@ -517,6 +684,20 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 0E833A82274BC39C008EA397 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0E833A93274BC3B1008EA397 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -525,7 +706,8 @@ buildActionMask = 2147483647; files = ( 0E0541D825A2355000EFC5FF /* Configuration.swift in Sources */, - 0E05418825A2334500EFC5FF /* ViewController.swift in Sources */, + 0E81EB4C274BACF200E5F2D3 /* WireGuardViewController.swift in Sources */, + 0E05418825A2334500EFC5FF /* OpenVPNViewController.swift in Sources */, 0E05418725A2334500EFC5FF /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -534,7 +716,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 0E0541D125A2354500EFC5FF /* PacketTunnelProvider.swift in Sources */, + 0E0541D125A2354500EFC5FF /* OpenVPNPacketTunnelProvider.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -543,8 +725,9 @@ buildActionMask = 2147483647; files = ( 0E0542B925A23A8100EFC5FF /* Configuration.swift in Sources */, + 0E81EB4F274BAE0A00E5F2D3 /* WireGuardViewController.swift in Sources */, 0E05425825A2392E00EFC5FF /* AppDelegate.swift in Sources */, - 0E05425925A2392E00EFC5FF /* ViewController.swift in Sources */, + 0E05425925A2392E00EFC5FF /* OpenVPNViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -552,7 +735,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 0E0542C225A23A8400EFC5FF /* PacketTunnelProvider.swift in Sources */, + 0E0542C225A23A8400EFC5FF /* OpenVPNPacketTunnelProvider.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -565,19 +748,55 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 0E833A80274BC39C008EA397 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E833AAD274BC64F008EA397 /* WireGuardPacketTunnelProvider.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0E833A91274BC3B1008EA397 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E833AAE274BC64F008EA397 /* WireGuardPacketTunnelProvider.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 0E0541A825A2343500EFC5FF /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 0E05419E25A2343500EFC5FF /* TunnelKitDemoTunnel-iOS */; + target = 0E05419E25A2343500EFC5FF /* TunnelKitDemoOpenVPNTunnel-iOS */; targetProxy = 0E0541A725A2343500EFC5FF /* PBXContainerItemProxy */; }; 0E05427F25A239C600EFC5FF /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 0E05427625A239C600EFC5FF /* TunnelKitDemoTunnel-macOS */; + target = 0E05427625A239C600EFC5FF /* TunnelKitDemoOpenVPNTunnel-macOS */; targetProxy = 0E05427E25A239C600EFC5FF /* PBXContainerItemProxy */; }; + 0E833A8C274BC39C008EA397 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0E833A83274BC39C008EA397 /* TunnelKitDemoWireGuardTunnel-iOS */; + targetProxy = 0E833A8B274BC39C008EA397 /* PBXContainerItemProxy */; + }; + 0E833A9D274BC3B1008EA397 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0E833A94274BC3B1008EA397 /* TunnelKitDemoWireGuardTunnel-macOS */; + targetProxy = 0E833A9C274BC3B1008EA397 /* PBXContainerItemProxy */; + }; + 0E833AA7274BC496008EA397 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0E81EB54274BB0D000E5F2D3 /* TunnelKitDemoWireGuardKitGo-macOS */; + targetProxy = 0E833AA6274BC496008EA397 /* PBXContainerItemProxy */; + }; + 0E833AA9274BC49B008EA397 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0EDD211D274BB4CF006833D1 /* TunnelKitDemoWireGuardKitGo-iOS */; + targetProxy = 0E833AA8274BC49B008EA397 /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ @@ -627,6 +846,7 @@ 0E05417B25A2330100EFC5FF /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_ENTITLEMENTS = Demo/iOS/Demo.entitlements; @@ -641,7 +861,6 @@ MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.ios.TunnelKit.Demo; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -649,6 +868,7 @@ 0E05417C25A2330100EFC5FF /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_ENTITLEMENTS = Demo/iOS/Demo.entitlements; @@ -662,7 +882,6 @@ MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.ios.TunnelKit.Demo; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; @@ -674,7 +893,7 @@ CODE_SIGN_ENTITLEMENTS = Demo/iOS/DemoTunnel.entitlements; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = DTDYD63ZX9; - INFOPLIST_FILE = "$(SRCROOT)/Demo/DemoTunnel.plist"; + INFOPLIST_FILE = Demo/DemoTunnel.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -682,10 +901,9 @@ ); MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.ios.TunnelKit.Demo.Tunnel; + PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.ios.TunnelKit.Demo.OpenVPN.Tunnel; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -697,17 +915,16 @@ CODE_SIGN_ENTITLEMENTS = Demo/iOS/DemoTunnel.entitlements; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = DTDYD63ZX9; - INFOPLIST_FILE = "$(SRCROOT)/Demo/DemoTunnel.plist"; + INFOPLIST_FILE = Demo/DemoTunnel.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.ios.TunnelKit.Demo.Tunnel; + PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.ios.TunnelKit.Demo.OpenVPN.Tunnel; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; @@ -715,6 +932,7 @@ 0E05423925A236EE00EFC5FF /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_ENTITLEMENTS = Demo/macOS/Demo.entitlements; @@ -733,13 +951,13 @@ PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.macos.TunnelKit.Demo; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; - SWIFT_VERSION = 5.0; }; name = Debug; }; 0E05423A25A236EE00EFC5FF /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_ENTITLEMENTS = Demo/macOS/Demo.entitlements; @@ -757,7 +975,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.macos.TunnelKit.Demo; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; - SWIFT_VERSION = 5.0; }; name = Release; }; @@ -770,7 +987,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = DTDYD63ZX9; ENABLE_HARDENED_RUNTIME = YES; - INFOPLIST_FILE = "$(SRCROOT)/Demo/DemoTunnel.plist"; + INFOPLIST_FILE = Demo/DemoTunnel.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", @@ -778,11 +995,10 @@ ); MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.macos.TunnelKit.Demo.Tunnel; + PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.macos.TunnelKit.Demo.OpenVPN.Tunnel; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SKIP_INSTALL = YES; - SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -795,18 +1011,17 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = DTDYD63ZX9; ENABLE_HARDENED_RUNTIME = YES; - INFOPLIST_FILE = "$(SRCROOT)/Demo/DemoTunnel.plist"; + INFOPLIST_FILE = Demo/DemoTunnel.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", "@executable_path/../../../../Frameworks", ); MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.macos.TunnelKit.Demo.Tunnel; + PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.macos.TunnelKit.Demo.OpenVPN.Tunnel; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SKIP_INSTALL = YES; - SWIFT_VERSION = 5.0; }; name = Release; }; @@ -905,10 +1120,11 @@ MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; + PATH = "${PATH}:/opt/homebrew/bin"; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -964,16 +1180,173 @@ IPHONEOS_DEPLOYMENT_TARGET = 12.0; MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; + PATH = "${PATH}:/opt/homebrew/bin"; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; + 0E81EB56274BB0D000E5F2D3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + 0E81EB57274BB0D000E5F2D3 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; + 0E833A8F274BC39C008EA397 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CODE_SIGN_ENTITLEMENTS = Demo/iOS/DemoTunnel.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = DTDYD63ZX9; + INFOPLIST_FILE = Demo/DemoTunnel.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.ios.TunnelKit.Demo.WireGuard.Tunnel; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 0E833A90274BC39C008EA397 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CODE_SIGN_ENTITLEMENTS = Demo/iOS/DemoTunnel.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = DTDYD63ZX9; + INFOPLIST_FILE = Demo/DemoTunnel.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.ios.TunnelKit.Demo.WireGuard.Tunnel; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 0E833AA0274BC3B2008EA397 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CODE_SIGN_ENTITLEMENTS = Demo/macOS/DemoTunnel.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = DTDYD63ZX9; + ENABLE_HARDENED_RUNTIME = YES; + INFOPLIST_FILE = Demo/DemoTunnel.plist; + INFOPLIST_KEY_CFBundleDisplayName = "TunnelKitDemoWireGuardTunnel-macOS"; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2021 Davide De Rosa. All rights reserved."; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@executable_path/../../../../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 12.0; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.macos.TunnelKit.Demo.WireGuard.Tunnel; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 0E833AA1274BC3B2008EA397 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CODE_SIGN_ENTITLEMENTS = Demo/macOS/DemoTunnel.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = DTDYD63ZX9; + ENABLE_HARDENED_RUNTIME = YES; + INFOPLIST_FILE = Demo/DemoTunnel.plist; + INFOPLIST_KEY_CFBundleDisplayName = "TunnelKitDemoWireGuardTunnel-macOS"; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2021 Davide De Rosa. All rights reserved."; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@executable_path/../../../../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 12.0; + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.macos.TunnelKit.Demo.WireGuard.Tunnel; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 0EDD211F274BB4CF006833D1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 0EDD2120274BB4CF006833D1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -986,7 +1359,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 0E0541AA25A2343500EFC5FF /* Build configuration list for PBXNativeTarget "TunnelKitDemoTunnel-iOS" */ = { + 0E0541AA25A2343500EFC5FF /* Build configuration list for PBXNativeTarget "TunnelKitDemoOpenVPNTunnel-iOS" */ = { isa = XCConfigurationList; buildConfigurations = ( 0E0541AB25A2343500EFC5FF /* Debug */, @@ -1004,7 +1377,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 0E05428125A239C600EFC5FF /* Build configuration list for PBXNativeTarget "TunnelKitDemoTunnel-macOS" */ = { + 0E05428125A239C600EFC5FF /* Build configuration list for PBXNativeTarget "TunnelKitDemoOpenVPNTunnel-macOS" */ = { isa = XCConfigurationList; buildConfigurations = ( 0E05428225A239C600EFC5FF /* Debug */, @@ -1031,6 +1404,42 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 0E81EB55274BB0D000E5F2D3 /* Build configuration list for PBXLegacyTarget "TunnelKitDemoWireGuardKitGo-macOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0E81EB56274BB0D000E5F2D3 /* Debug */, + 0E81EB57274BB0D000E5F2D3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0E833A8E274BC39C008EA397 /* Build configuration list for PBXNativeTarget "TunnelKitDemoWireGuardTunnel-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0E833A8F274BC39C008EA397 /* Debug */, + 0E833A90274BC39C008EA397 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0E833A9F274BC3B2008EA397 /* Build configuration list for PBXNativeTarget "TunnelKitDemoWireGuardTunnel-macOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0E833AA0274BC3B2008EA397 /* Debug */, + 0E833AA1274BC3B2008EA397 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0EDD211E274BB4CF006833D1 /* Build configuration list for PBXLegacyTarget "TunnelKitDemoWireGuardKitGo-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0EDD211F274BB4CF006833D1 /* Debug */, + 0EDD2120274BB4CF006833D1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ /* Begin XCSwiftPackageProductDependency section */ @@ -1042,6 +1451,22 @@ isa = XCSwiftPackageProductDependency; productName = TunnelKitOpenVPNAppExtension; }; + 0E81EB50274BB02100E5F2D3 /* TunnelKitWireGuard */ = { + isa = XCSwiftPackageProductDependency; + productName = TunnelKitWireGuard; + }; + 0E81EB52274BB02600E5F2D3 /* TunnelKitWireGuard */ = { + isa = XCSwiftPackageProductDependency; + productName = TunnelKitWireGuard; + }; + 0E833AA2274BC480008EA397 /* TunnelKitWireGuardAppExtension */ = { + isa = XCSwiftPackageProductDependency; + productName = TunnelKitWireGuardAppExtension; + }; + 0E833AA4274BC484008EA397 /* TunnelKitWireGuardAppExtension */ = { + isa = XCSwiftPackageProductDependency; + productName = TunnelKitWireGuardAppExtension; + }; 0EFD5B302727250500C7D5FD /* TunnelKitOpenVPN */ = { isa = XCSwiftPackageProductDependency; productName = TunnelKitOpenVPN; diff --git a/Demo/TunnelKit.xcodeproj/xcshareddata/xcschemes/TunnelKitDemoTunnel-iOS.xcscheme b/Demo/TunnelKit.xcodeproj/xcshareddata/xcschemes/TunnelKitDemoOpenVPNTunnel-iOS.xcscheme similarity index 77% rename from Demo/TunnelKit.xcodeproj/xcshareddata/xcschemes/TunnelKitDemoTunnel-iOS.xcscheme rename to Demo/TunnelKit.xcodeproj/xcshareddata/xcschemes/TunnelKitDemoOpenVPNTunnel-iOS.xcscheme index d709fb6..b102911 100644 --- a/Demo/TunnelKit.xcodeproj/xcshareddata/xcschemes/TunnelKitDemoTunnel-iOS.xcscheme +++ b/Demo/TunnelKit.xcodeproj/xcshareddata/xcschemes/TunnelKitDemoOpenVPNTunnel-iOS.xcscheme @@ -16,8 +16,8 @@ @@ -57,16 +57,6 @@ debugServiceExtension = "internal" allowLocationSimulation = "YES" launchAutomaticallySubstyle = "2"> - - - - - + - + diff --git a/Demo/TunnelKit.xcodeproj/xcshareddata/xcschemes/TunnelKitDemoTunnel-macOS.xcscheme b/Demo/TunnelKit.xcodeproj/xcshareddata/xcschemes/TunnelKitDemoOpenVPNTunnel-macOS.xcscheme similarity index 77% rename from Demo/TunnelKit.xcodeproj/xcshareddata/xcschemes/TunnelKitDemoTunnel-macOS.xcscheme rename to Demo/TunnelKit.xcodeproj/xcshareddata/xcschemes/TunnelKitDemoOpenVPNTunnel-macOS.xcscheme index a2b3b2a..a593f03 100644 --- a/Demo/TunnelKit.xcodeproj/xcshareddata/xcschemes/TunnelKitDemoTunnel-macOS.xcscheme +++ b/Demo/TunnelKit.xcodeproj/xcshareddata/xcschemes/TunnelKitDemoOpenVPNTunnel-macOS.xcscheme @@ -16,8 +16,8 @@ @@ -57,16 +57,6 @@ debugServiceExtension = "internal" allowLocationSimulation = "YES" launchAutomaticallySubstyle = "2"> - - - - - + - + diff --git a/Demo/TunnelKit.xcodeproj/xcshareddata/xcschemes/TunnelKitDemoWireGuardTunnel-iOS.xcscheme b/Demo/TunnelKit.xcodeproj/xcshareddata/xcschemes/TunnelKitDemoWireGuardTunnel-iOS.xcscheme new file mode 100644 index 0000000..d5801ea --- /dev/null +++ b/Demo/TunnelKit.xcodeproj/xcshareddata/xcschemes/TunnelKitDemoWireGuardTunnel-iOS.xcscheme @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Demo/TunnelKit.xcodeproj/xcshareddata/xcschemes/TunnelKitDemoWireGuardTunnel-macOS.xcscheme b/Demo/TunnelKit.xcodeproj/xcshareddata/xcschemes/TunnelKitDemoWireGuardTunnel-macOS.xcscheme new file mode 100644 index 0000000..8712027 --- /dev/null +++ b/Demo/TunnelKit.xcodeproj/xcshareddata/xcschemes/TunnelKitDemoWireGuardTunnel-macOS.xcscheme @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Package.resolved b/Package.resolved index b4b65f0..34adf8e 100644 --- a/Package.resolved +++ b/Package.resolved @@ -18,6 +18,15 @@ "revision": "2c039501d6eeb4d4cd4aec4a8d884ad28862e044", "version": "1.9.5" } + }, + { + "package": "WireGuardKit", + "repositoryURL": "https://git.zx2c4.com/wireguard-apple", + "state": { + "branch": null, + "revision": "10da5cfdef362889b438cfbeff867a74e6d717fd", + "version": "1.0.15-26" + } } ] }, diff --git a/Package.swift b/Package.swift index 3e35f92..8bd26a3 100644 --- a/Package.swift +++ b/Package.swift @@ -6,7 +6,7 @@ import PackageDescription let package = Package( name: "TunnelKit", platforms: [ - .iOS(.v11), .macOS(.v10_15) + .iOS(.v12), .macOS(.v10_15) ], products: [ // Products define the executables and libraries a package produces, and make them visible to other packages. @@ -26,6 +26,14 @@ let package = Package( name: "TunnelKitOpenVPNAppExtension", targets: ["TunnelKitOpenVPNAppExtension"] ), + .library( + name: "TunnelKitWireGuard", + targets: ["TunnelKitWireGuard"] + ), + .library( + name: "TunnelKitWireGuardAppExtension", + targets: ["TunnelKitWireGuardAppExtension"] + ), .library( name: "TunnelKitLZO", targets: ["TunnelKitLZO"] @@ -35,7 +43,8 @@ let package = Package( // Dependencies declare other packages that this package depends on. // .package(url: /* package url */, from: "1.0.0"), .package(url: "https://github.com/SwiftyBeaver/SwiftyBeaver", from: "1.9.0"), - .package(url: "https://github.com/passepartoutvpn/openssl-apple", from: "1.1.11200") + .package(url: "https://github.com/passepartoutvpn/openssl-apple", from: "1.1.11200"), + .package(name: "WireGuardKit", url: "https://git.zx2c4.com/wireguard-apple", .exact("1.0.15-26")) ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. @@ -103,6 +112,30 @@ let package = Package( "TunnelKitOpenVPNManager", "TunnelKitOpenVPNProtocol" ]), + // + .target( + name: "TunnelKitWireGuard", + dependencies: [ + "TunnelKitWireGuardCore", + "TunnelKitWireGuardManager" + ]), + .target( + name: "TunnelKitWireGuardCore", + dependencies: [ + "WireGuardKit" + ]), + .target( + name: "TunnelKitWireGuardManager", + dependencies: [ + "TunnelKitManager", + "TunnelKitWireGuardCore" + ]), + .target( + name: "TunnelKitWireGuardAppExtension", + dependencies: [ + "TunnelKitWireGuardCore", + "TunnelKitWireGuardManager" + ]), .target( name: "TunnelKitLZO", dependencies: [], diff --git a/README.md b/README.md index 10fbb80..faa11fe 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,19 @@ -![iOS 11+](https://img.shields.io/badge/iOS-11+-green.svg) -![macOS 10.15+](https://img.shields.io/badge/macOS-10.15+-green.svg) -[![License GPLv3](https://img.shields.io/badge/License-GPLv3-lightgray.svg)](LICENSE) -[![GitHub Actions](https://github.com/passepartoutvpn/tunnelkit/actions/workflows/test.yml/badge.svg)](https://github.com/passepartoutvpn/tunnelkit/actions/workflows/test.yml) +![iOS 12+](https://img.shields.io/badge/ios-12+-green.svg) +![macOS 10.15+](https://img.shields.io/badge/macos-10.15+-green.svg) +[![License GPLv3](https://img.shields.io/badge/license-GPLv3-lightgray.svg)](LICENSE) + +[![Unit Tests](https://github.com/passepartoutvpn/tunnelkit/actions/workflows/test.yml/badge.svg)](https://github.com/passepartoutvpn/tunnelkit/actions/workflows/test.yml) +[![Release](https://github.com/passepartoutvpn/tunnelkit/actions/workflows/release.yml/badge.svg)](https://github.com/passepartoutvpn/tunnelkit/actions/workflows/release.yml) # TunnelKit -This library provides a generic framework for VPN development and a simplified Swift/Obj-C implementation of the OpenVPN® protocol for the Apple platforms. The crypto layer is built on top of [OpenSSL 1.1.1][dep-openssl], which in turn enables support for a certain range of encryption and digest algorithms. +This library provides a generic framework for VPN development on Apple platforms. -## Getting started +## OpenVPN -The client is known to work with [OpenVPN®][openvpn] 2.3+ servers. +TunnelKit comes with a simplified Swift/Obj-C implementation of the [OpenVPN®][dep-openvpn] protocol, whose crypto layer is built on top of [OpenSSL 1.1.1][dep-openssl]. + +The client is known to work with OpenVPN® 2.3+ servers. - [x] Handshake and tunneling over UDP or TCP - [x] Ciphers @@ -67,11 +71,36 @@ TunnelKit can parse .ovpn configuration files. Below are a few details worth men Many other flags are ignored too but it's normally not an issue. +## WireGuard + +TunnelKit offers a user-friendly API to the modern [WireGuard®][dep-wireguard] protocol. + +### Manual Xcode steps + +If you add any `TunnelKitWireGuard*` Swift package to the "Link with binary libraries" section of your app or tunnel extension, you are bound to hit this error: + +``` +ld: library not found for -lwg-go +``` + +because part of the WireGuardKit package is based on `make`, which SwiftPM doesn't support yet. + +Therefore, make sure to follow the steps below for proper integration: + +- Copy `Scripts/build_wireguard_go_bridge.sh` somewhere in your project. +- In Xcode, click File -> New -> Target. Switch to "Other" tab and choose "External Build System". +- Type a name for your target. +- Open the "Info" tab and replace `/usr/bin/make` with `$(PROJECT_DIR)/path/to/build_wireguard_go_bridge.sh` in "Build Tool". +- Switch to "Build Settings" and find SDKROOT. Type in `macosx` if you target macOS, or type in `iphoneos` if you target iOS. +- Locate your tunnel extension target and switch to "Build Phases" tab. +- Locate "Dependencies" section and hit "+" to add the target you have just created. +- Repeat the process for each platform. + ## Installation ### Requirements -- iOS 11.0+ / macOS 10.15+ +- iOS 12.0+ / macOS 10.15+ - SwiftPM 5.3 - Git (preinstalled with Xcode Command Line Tools) @@ -79,7 +108,7 @@ It's highly recommended to use the Git package provided by [Homebrew][dep-brew]. ### Caveats -Make sure to set "Enable Bitcode" (iOS) to NO, otherwise the library [would not be able to link OpenSSL][about-pr-bitcode]. +Make sure to set "Enable Bitcode" (iOS) to NO, otherwise the library [would not be able to link OpenSSL][about-pr-bitcode] (OpenVPN) and the `wg-go` bridge (WireGuard). Recent versions of Xcode (latest is 13.1) have an issue where the "Frameworks" directory is replicated inside application extensions. This is not a blocker during development, but will prevent your archive from being validated against App Store Connect due to the following error: @@ -101,14 +130,14 @@ Download the library codebase locally: $ git clone https://github.com/passepartoutvpn/tunnelkit.git -There are demo targets containing a simple app for testing the tunnel, called `BasicTunnel`. Open `Demo/TunnelKit.xcodeproject` in Xcode and run it on both iOS and macOS. +There are demo targets containing a simple app for testing the tunnels. Open `Demo/TunnelKit.xcodeproject` in Xcode and run it on both iOS and macOS. -For the VPN to work properly, the `BasicTunnel` demo requires: +For the VPN to work properly, the demo requires: - _App Groups_ and _Keychain Sharing_ capabilities - App IDs with _Packet Tunnel_ entitlements -both in the main app and the tunnel extension target. +both in the main app and the tunnel extension targets. In order to test connectivity in your own environment, modify the file `Demo/Demo/Configuration.swift` to match your VPN server parameters. @@ -120,10 +149,10 @@ Example: -----END CERTIFICATE----- """) -Make sure to also update the following constants in the same files, according to your developer account and your target bundle identifiers: +Make sure to also update the following constants in the `*ViewController.swift` files, according to your developer account and your target bundle identifiers: - public static let appGroup - public static let tunnelIdentifier + private let appGroup = "..." + private let tunnelIdentifier = "..." Remember that the App Group on macOS requires a team ID prefix. @@ -133,51 +162,32 @@ The library is split into several modules, in order to decouple the low-level pr Full documentation of the public interface is available and can be generated by opening the package in Xcode and running "Build Documentation" (Xcode 13). -### TunnelKitCore - -Contains the building blocks of a VPN protocol. Eventually, a consumer would implement the `Session` interface, expected to start and control the VPN session. A session is expected to work with generic network interfaces: - -- `LinkInterface` (e.g. a socket) -- `TunnelInterface` (e.g. an `utun` interface) - -There are no physical network implementations (e.g. UDP or TCP) in this module. - -### TunnelKitManager +### TunnelKit This component includes convenient classes to control the VPN tunnel from your app without the NetworkExtension headaches. Have a look at `VPNProvider` implementations: - `MockVPNProvider` (default, useful to test on simulator) - `NetworkExtensionVPNProvider` (anything based on NetworkExtension) -### TunnelKitAppExtension - -Provides a layer on top of the NetworkExtension framework. Most importantly, bridges native [NWUDPSession][ne-udp] and [NWTCPConnection][ne-tcp] to an abstract `GenericSocket` interface, thus making a multi-protocol VPN dramatically easier to manage. - ### TunnelKitIKE Here you find `NativeProvider`, a generic way to manage a VPN profile based on the native IPSec/IKEv2 protocols. Just wrap a `NEVPNProtocolIPSec` or `NEVPNProtocolIKEv2` object in a `NetworkExtensionVPNConfiguration` and use it to install or connect to the VPN. -### TunnelKitOpenVPN* +### TunnelKitOpenVPN -#### Protocol +Provides the entities to interact with the OpenVPN tunnel. -Here are the low-level entities on top of which an OpenVPN connection is established. Code is mixed Swift and Obj-C, most of it is not exposed to consumers. The protocol implementation in particular depends on OpenSSL. +### TunnelKitOpenVPNAppExtension -The entry point is the `OpenVPNSession` class. The networking layer is fully abstract and delegated externally with the use of opaque `IOInterface` (`LinkInterface` and `TunnelInterface`) and `OpenVPNSessionDelegate` protocols. +Contains the `NEPacketTunnelProvider` implementation of a OpenVPN tunnel. -#### AppExtension +### TunnelKitWireGuard -Another goal of this area is packaging up a black box implementation of a [NEPacketTunnelProvider][ne-ptp], which is the essential part of a Packet Tunnel Provider app extension. You will find the main implementation in the `OpenVPNTunnelProvider` class. +Provides the entities to interact with the WireGuard tunnel. -A debug log snapshot is optionally maintained and shared by the tunnel provider to host apps via the App Group container. +### TunnelKitWireGuardAppExtension -#### Manager - -On the client side, you manage the VPN profile with the `OpenVPNProvider` class, which is a specific implementation of `NetworkExtensionVPNProvider`. - -### TunnelKitLZO - -Due to the restrictive license (GPLv2), LZO support is provided as an optional component. +Contains the `NEPacketTunnelProvider` implementation of a WireGuard tunnel. ## License @@ -210,20 +220,29 @@ For more details please see [CONTRIBUTING][contrib-readme]. - [SURFnet][ppl-surfnet] - [SwiftyBeaver][dep-swiftybeaver-repo] - Copyright (c) 2015 Sebastian Kreutzberger - [XMB5][ppl-xmb5] for the [XOR patch][ppl-xmb5-xor] - Copyright (c) 2020 Sam Foxman +- [eduVPN][ppl-eduvpn] for the convenient WireGuardKitGo script -This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. ([https://www.openssl.org/][dep-openssl]) +### OpenVPN Copyright (c) 2002-2018 OpenVPN Inc. - OpenVPN is a registered trademark of OpenVPN Inc. +### WireGuard + +© Copyright 2015-2021 Jason A. Donenfeld. All Rights Reserved. "WireGuard" and the "WireGuard" logo are registered trademarks of Jason A. Donenfeld. + +### OpenSSL + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. ([https://www.openssl.org/][dep-openssl]) + ## Contacts Twitter: [@keeshux][about-twitter] Website: [passepartoutvpn.app][about-website] -[openvpn]: https://openvpn.net/index.php/open-source/overview.html - [dep-brew]: https://brew.sh/ +[dep-openvpn]: https://openvpn.net/index.php/open-source/overview.html +[dep-wireguard]: https://www.wireguard.com/ [dep-openssl]: https://www.openssl.org/ [ne-home]: https://developer.apple.com/documentation/networkextension @@ -243,6 +262,7 @@ Website: [passepartoutvpn.app][about-website] [ppl-surfnet]: https://www.surf.nl/en/about-surf/subsidiaries/surfnet [ppl-xmb5]: https://github.com/XMB5 [ppl-xmb5-xor]: https://github.com/passepartoutvpn/tunnelkit/pull/170 +[ppl-eduvpn]: https://github.com/eduvpn/apple [about-tunnelblick-xor]: https://tunnelblick.net/cOpenvpn_xorpatch.html [about-pr-bitcode]: https://github.com/passepartoutvpn/tunnelkit/issues/51 diff --git a/Scripts/build_wireguard_go_bridge.sh b/Scripts/build_wireguard_go_bridge.sh new file mode 100755 index 0000000..ab6fa84 --- /dev/null +++ b/Scripts/build_wireguard_go_bridge.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +# build_wireguard_go_bridge.sh - Builds WireGuardKitGo +# +# Figures out the directory where the wireguard-apple SPM package +# is checked out by Xcode (so that it works when building as well as +# archiving), then cd-s to the WireGuardKitGo directory +# and runs make there. + +project_data_dir="$BUILD_DIR" + +# The wireguard-apple README suggests using ${BUILD_DIR%Build/*}, which +# doesn't seem to work. So here, we do the equivalent in script. + +while true; do + parent_dir=$(dirname "$project_data_dir") + basename=$(basename "$project_data_dir") + project_data_dir="$parent_dir" + if [ "$basename" = "Build" ]; then + break + fi +done + +# The wireguard-apple README looks into +# SourcePackages/checkouts/wireguard-apple, but Xcode seems to place the +# sources in SourcePackages/checkouts/ so just playing it safe and +# trying both. + +checkouts_dir="$project_data_dir"/SourcePackages/checkouts +if [ -e "$checkouts_dir"/wireguard-apple ]; then + checkouts_dir="$checkouts_dir"/wireguard-apple +fi + +wireguard_go_dir="$checkouts_dir"/Sources/WireGuardKitGo + +# To ensure we have Go in our path, we add where +# Homebrew generally installs executables +export PATH=${PATH}:/usr/local/bin:/opt/homebrew/bin + +cd "$wireguard_go_dir" && /usr/bin/make diff --git a/Sources/TunnelKitWireGuard/Exports.swift b/Sources/TunnelKitWireGuard/Exports.swift new file mode 100644 index 0000000..1956691 --- /dev/null +++ b/Sources/TunnelKitWireGuard/Exports.swift @@ -0,0 +1,2 @@ +@_exported import TunnelKitWireGuardCore +@_exported import TunnelKitWireGuardManager diff --git a/Sources/TunnelKitWireGuardAppExtension/Internal/ErrorNotifier.swift b/Sources/TunnelKitWireGuardAppExtension/Internal/ErrorNotifier.swift new file mode 100644 index 0000000..37b7e7f --- /dev/null +++ b/Sources/TunnelKitWireGuardAppExtension/Internal/ErrorNotifier.swift @@ -0,0 +1,42 @@ +import TunnelKitWireGuardCore +import TunnelKitWireGuardManager + +// SPDX-License-Identifier: MIT +// Copyright © 2018-2021 WireGuard LLC. All Rights Reserved. + +import NetworkExtension + +class ErrorNotifier { + private let appGroupId: String + + private var sharedFolderURL: URL? { + guard let sharedFolderURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupId) else { + wg_log(.error, message: "Cannot obtain shared folder URL") + return nil + } + return sharedFolderURL + } + + init(appGroupId: String) { + self.appGroupId = appGroupId + removeLastErrorFile() + } + + func notify(_ error: WireGuardProviderError) { + guard let lastErrorFilePath = networkExtensionLastErrorFileURL?.path else { + return + } + let errorMessageData = "\(error)".data(using: .utf8) + FileManager.default.createFile(atPath: lastErrorFilePath, contents: errorMessageData, attributes: nil) + } + + func removeLastErrorFile() { + if let lastErrorFileURL = networkExtensionLastErrorFileURL { + try? FileManager.default.removeItem(at: lastErrorFileURL) + } + } + + private var networkExtensionLastErrorFileURL: URL? { + return sharedFolderURL?.appendingPathComponent("last-error.txt") + } +} diff --git a/Sources/TunnelKitWireGuardAppExtension/WireGuardTunnelProvider.swift b/Sources/TunnelKitWireGuardAppExtension/WireGuardTunnelProvider.swift new file mode 100644 index 0000000..3752b0c --- /dev/null +++ b/Sources/TunnelKitWireGuardAppExtension/WireGuardTunnelProvider.swift @@ -0,0 +1,134 @@ +import TunnelKitWireGuardCore +import TunnelKitWireGuardManager +import WireGuardKit + +// SPDX-License-Identifier: MIT +// Copyright © 2018-2021 WireGuard LLC. All Rights Reserved. + +import Foundation +import NetworkExtension +import os + +open class WireGuardTunnelProvider: NEPacketTunnelProvider { + private var persistentErrorNotifier: ErrorNotifier? + + private lazy var adapter: WireGuardAdapter = { + return WireGuardAdapter(with: self) { logLevel, message in + wg_log(logLevel.osLogLevel, message: message) + } + }() + + open override func startTunnel(options: [String: NSObject]?, completionHandler: @escaping (Error?) -> Void) { + + // BEGIN: TunnelKit + + guard let tunnelProviderProtocol = protocolConfiguration as? NETunnelProviderProtocol else { + fatalError("Not a NETunnelProviderProtocol") + } + guard let appGroup = tunnelProviderProtocol.providerConfiguration?["AppGroup"] as? String else { + fatalError("AppGroup not found in providerConfiguration") + } + let errorNotifier = ErrorNotifier(appGroupId: appGroup) + persistentErrorNotifier = errorNotifier + + let tunnelConfiguration: TunnelConfiguration + do { + tunnelConfiguration = try WireGuardProvider.Configuration.parsed(from: tunnelProviderProtocol).tunnelConfiguration + } catch { + errorNotifier.notify(WireGuardProviderError.savedProtocolConfigurationIsInvalid) + completionHandler(WireGuardProviderError.savedProtocolConfigurationIsInvalid) + return + } + + // END: TunnelKit + + // Start the tunnel + adapter.start(tunnelConfiguration: tunnelConfiguration) { adapterError in + guard let adapterError = adapterError else { + let interfaceName = self.adapter.interfaceName ?? "unknown" + + wg_log(.info, message: "Tunnel interface is \(interfaceName)") + + completionHandler(nil) + return + } + + switch adapterError { + case .cannotLocateTunnelFileDescriptor: + wg_log(.error, staticMessage: "Starting tunnel failed: could not determine file descriptor") + errorNotifier.notify(WireGuardProviderError.couldNotDetermineFileDescriptor) + completionHandler(WireGuardProviderError.couldNotDetermineFileDescriptor) + + case .dnsResolution(let dnsErrors): + let hostnamesWithDnsResolutionFailure = dnsErrors.map { $0.address } + .joined(separator: ", ") + wg_log(.error, message: "DNS resolution failed for the following hostnames: \(hostnamesWithDnsResolutionFailure)") + errorNotifier.notify(WireGuardProviderError.dnsResolutionFailure) + completionHandler(WireGuardProviderError.dnsResolutionFailure) + + case .setNetworkSettings(let error): + wg_log(.error, message: "Starting tunnel failed with setTunnelNetworkSettings returning \(error.localizedDescription)") + errorNotifier.notify(WireGuardProviderError.couldNotSetNetworkSettings) + completionHandler(WireGuardProviderError.couldNotSetNetworkSettings) + + case .startWireGuardBackend(let errorCode): + wg_log(.error, message: "Starting tunnel failed with wgTurnOn returning \(errorCode)") + errorNotifier.notify(WireGuardProviderError.couldNotStartBackend) + completionHandler(WireGuardProviderError.couldNotStartBackend) + + case .invalidState: + // Must never happen + fatalError() + } + } + } + + open override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { + wg_log(.info, staticMessage: "Stopping tunnel") + + adapter.stop { error in + // BEGIN: TunnelKit + self.persistentErrorNotifier?.removeLastErrorFile() + // END: TunnelKit + + if let error = error { + wg_log(.error, message: "Failed to stop WireGuard adapter: \(error.localizedDescription)") + } + completionHandler() + + #if os(macOS) + // HACK: This is a filthy hack to work around Apple bug 32073323 (dup'd by us as 47526107). + // Remove it when they finally fix this upstream and the fix has been rolled out to + // sufficient quantities of users. + exit(0) + #endif + } + } + + open override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)? = nil) { + guard let completionHandler = completionHandler else { return } + + if messageData.count == 1 && messageData[0] == 0 { + adapter.getRuntimeConfiguration { settings in + var data: Data? + if let settings = settings { + data = settings.data(using: .utf8)! + } + completionHandler(data) + } + } else { + completionHandler(nil) + } + } +} + +extension WireGuardLogLevel { + var osLogLevel: OSLogType { + switch self { + case .verbose: + return .debug + case .error: + return .error + } + } +} diff --git a/Sources/TunnelKitWireGuardCore/Configuration+WireGuardKit.swift b/Sources/TunnelKitWireGuardCore/Configuration+WireGuardKit.swift new file mode 100644 index 0000000..e5e8759 --- /dev/null +++ b/Sources/TunnelKitWireGuardCore/Configuration+WireGuardKit.swift @@ -0,0 +1,48 @@ +// +// Configuration+WireGuardKit.swift +// TunnelKit +// +// Created by Davide De Rosa on 11/23/21. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of TunnelKit. +// +// TunnelKit is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// TunnelKit is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with TunnelKit. If not, see . +// + +import Foundation +import WireGuardKit + +extension WireGuard.Configuration { + public init(wgQuickConfig: String) throws { + tunnelConfiguration = try TunnelConfiguration(fromWgQuickConfig: wgQuickConfig) + } + + public func asWgQuickConfig() -> String { + return tunnelConfiguration.asWgQuickConfig() + } + + public var endpointRepresentation: String { + let endpoints = tunnelConfiguration.peers.compactMap { $0.endpoint } + if endpoints.count == 1 { + return endpoints[0].stringRepresentation + } else if endpoints.isEmpty { + return "Unspecified" + } else { + return "Multiple endpoints" + } + } +} diff --git a/Sources/TunnelKitWireGuardCore/Configuration.swift b/Sources/TunnelKitWireGuardCore/Configuration.swift new file mode 100644 index 0000000..053c9a0 --- /dev/null +++ b/Sources/TunnelKitWireGuardCore/Configuration.swift @@ -0,0 +1,99 @@ +// +// Configuration.swift +// TunnelKit +// +// Created by Davide De Rosa on 11/23/21. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of TunnelKit. +// +// TunnelKit is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// TunnelKit is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with TunnelKit. If not, see . +// + +import Foundation +import WireGuardKit + +extension WireGuard { + public struct ConfigurationBuilder { + public var privateKey: String? + + public var addresses: [String]? + + public var dns: [String]? + + public var mtu: UInt16? + + public var peerPublicKey: String? + + public var peerPreSharedKey: String? + + public var peerAddress: String? + + public var peerPort: UInt16? + + public var allowedIPs: [String]? + + public var keepAliveInterval: UInt16? + + public init() { + } + + public func build() -> Configuration? { + guard let privateKey = privateKey, let clientPrivateKey = PrivateKey(base64Key: privateKey) else { + return nil + } + guard let peerPublicKey = peerPublicKey, let serverPublicKey = PublicKey(base64Key: peerPublicKey) else { + return nil + } + guard let peerAddress = peerAddress, let peerPort = peerPort, let endpoint = Endpoint(from: "\(peerAddress):\(peerPort)") else { + return nil + } + + var interfaceConfiguration = InterfaceConfiguration(privateKey: clientPrivateKey) + if let clientAddresses = addresses?.mapOptional({ IPAddressRange(from: $0) }) { + interfaceConfiguration.addresses = clientAddresses + } + if let dnsServers = dns?.mapOptional({ DNSServer(from: $0) }) { + interfaceConfiguration.dns = dnsServers + } + interfaceConfiguration.mtu = mtu + var peerConfiguration = PeerConfiguration(publicKey: serverPublicKey) + if let peerPreSharedKey = peerPreSharedKey { + peerConfiguration.preSharedKey = PreSharedKey(base64Key: peerPreSharedKey) + } + if let peerAllowedIPs = allowedIPs?.mapOptional({ IPAddressRange(from: $0) }) { + peerConfiguration.allowedIPs = peerAllowedIPs + } + peerConfiguration.endpoint = endpoint + peerConfiguration.persistentKeepAlive = keepAliveInterval + + let tunnelConfiguration = TunnelConfiguration(name: nil, interface: interfaceConfiguration, peers: [peerConfiguration]) + return Configuration(tunnelConfiguration: tunnelConfiguration) + } + } + + public struct Configuration { + public let tunnelConfiguration: TunnelConfiguration + } +} + +private extension Array { + func mapOptional(_ transform: (Self.Element) throws -> V?) rethrows -> [V] { + return try map(transform) + .filter { $0 != nil } + .map { $0! } + } +} diff --git a/Sources/TunnelKitWireGuardCore/Internal/Logger.swift b/Sources/TunnelKitWireGuardCore/Internal/Logger.swift new file mode 100644 index 0000000..8676835 --- /dev/null +++ b/Sources/TunnelKitWireGuardCore/Internal/Logger.swift @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +// Copyright © 2018-2021 WireGuard LLC. All Rights Reserved. + +import Foundation +import os.log + +public func wg_log(_ type: OSLogType, staticMessage msg: StaticString) { + os_log(msg, log: OSLog.default, type: type) +} + +public func wg_log(_ type: OSLogType, message msg: String) { + os_log("%{public}s", log: OSLog.default, type: type, msg) +} diff --git a/Sources/TunnelKitWireGuardCore/Internal/String+ArrayConversion.swift b/Sources/TunnelKitWireGuardCore/Internal/String+ArrayConversion.swift new file mode 100644 index 0000000..adb959f --- /dev/null +++ b/Sources/TunnelKitWireGuardCore/Internal/String+ArrayConversion.swift @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT +// Copyright © 2018-2021 WireGuard LLC. All Rights Reserved. + +import Foundation + +extension String { + + func splitToArray(separator: Character = ",", trimmingCharacters: CharacterSet? = nil) -> [String] { + return split(separator: separator) + .map { + if let charSet = trimmingCharacters { + return $0.trimmingCharacters(in: charSet) + } else { + return String($0) + } + } + } + +} + +extension Optional where Wrapped == String { + + func splitToArray(separator: Character = ",", trimmingCharacters: CharacterSet? = nil) -> [String] { + switch self { + case .none: + return [] + case .some(let wrapped): + return wrapped.splitToArray(separator: separator, trimmingCharacters: trimmingCharacters) + } + } + +} diff --git a/Sources/TunnelKitWireGuardCore/Internal/TunnelConfiguration+WgQuickConfig.swift b/Sources/TunnelKitWireGuardCore/Internal/TunnelConfiguration+WgQuickConfig.swift new file mode 100644 index 0000000..72b6e36 --- /dev/null +++ b/Sources/TunnelKitWireGuardCore/Internal/TunnelConfiguration+WgQuickConfig.swift @@ -0,0 +1,254 @@ +import WireGuardKit + +// SPDX-License-Identifier: MIT +// Copyright © 2018-2021 WireGuard LLC. All Rights Reserved. + +import Foundation + +extension TunnelConfiguration { + + enum ParserState { + case inInterfaceSection + case inPeerSection + case notInASection + } + + enum ParseError: Error { + case invalidLine(String.SubSequence) + case noInterface + case multipleInterfaces + case interfaceHasNoPrivateKey + case interfaceHasInvalidPrivateKey(String) + case interfaceHasInvalidListenPort(String) + case interfaceHasInvalidAddress(String) + case interfaceHasInvalidDNS(String) + case interfaceHasInvalidMTU(String) + case interfaceHasUnrecognizedKey(String) + case peerHasNoPublicKey + case peerHasInvalidPublicKey(String) + case peerHasInvalidPreSharedKey(String) + case peerHasInvalidAllowedIP(String) + case peerHasInvalidEndpoint(String) + case peerHasInvalidPersistentKeepAlive(String) + case peerHasInvalidTransferBytes(String) + case peerHasInvalidLastHandshakeTime(String) + case peerHasUnrecognizedKey(String) + case multiplePeersWithSamePublicKey + case multipleEntriesForKey(String) + } + + convenience init(fromWgQuickConfig wgQuickConfig: String, called name: String? = nil) throws { + var interfaceConfiguration: InterfaceConfiguration? + var peerConfigurations = [PeerConfiguration]() + + let lines = wgQuickConfig.split { $0.isNewline } + + var parserState = ParserState.notInASection + var attributes = [String: String]() + + for (lineIndex, line) in lines.enumerated() { + var trimmedLine: String + if let commentRange = line.range(of: "#") { + trimmedLine = String(line[.. = ["privatekey", "listenport", "address", "dns", "mtu"] + let peerSectionKeys: Set = ["publickey", "presharedkey", "allowedips", "endpoint", "persistentkeepalive"] + if parserState == .inInterfaceSection { + guard interfaceSectionKeys.contains(key) else { + throw ParseError.interfaceHasUnrecognizedKey(keyWithCase) + } + } else if parserState == .inPeerSection { + guard peerSectionKeys.contains(key) else { + throw ParseError.peerHasUnrecognizedKey(keyWithCase) + } + } + } else if lowercasedLine != "[interface]" && lowercasedLine != "[peer]" { + throw ParseError.invalidLine(line) + } + } + + let isLastLine = lineIndex == lines.count - 1 + + if isLastLine || lowercasedLine == "[interface]" || lowercasedLine == "[peer]" { + // Previous section has ended; process the attributes collected so far + if parserState == .inInterfaceSection { + let interface = try TunnelConfiguration.collate(interfaceAttributes: attributes) + guard interfaceConfiguration == nil else { throw ParseError.multipleInterfaces } + interfaceConfiguration = interface + } else if parserState == .inPeerSection { + let peer = try TunnelConfiguration.collate(peerAttributes: attributes) + peerConfigurations.append(peer) + } + } + + if lowercasedLine == "[interface]" { + parserState = .inInterfaceSection + attributes.removeAll() + } else if lowercasedLine == "[peer]" { + parserState = .inPeerSection + attributes.removeAll() + } + } + + let peerPublicKeysArray = peerConfigurations.map { $0.publicKey } + let peerPublicKeysSet = Set(peerPublicKeysArray) + if peerPublicKeysArray.count != peerPublicKeysSet.count { + throw ParseError.multiplePeersWithSamePublicKey + } + + if let interfaceConfiguration = interfaceConfiguration { + self.init(name: name, interface: interfaceConfiguration, peers: peerConfigurations) + } else { + throw ParseError.noInterface + } + } + + func asWgQuickConfig() -> String { + var output = "[Interface]\n" + output.append("PrivateKey = \(interface.privateKey.base64Key)\n") + if let listenPort = interface.listenPort { + output.append("ListenPort = \(listenPort)\n") + } + if !interface.addresses.isEmpty { + let addressString = interface.addresses.map { $0.stringRepresentation }.joined(separator: ", ") + output.append("Address = \(addressString)\n") + } + if !interface.dns.isEmpty || !interface.dnsSearch.isEmpty { + var dnsLine = interface.dns.map { $0.stringRepresentation } + dnsLine.append(contentsOf: interface.dnsSearch) + let dnsString = dnsLine.joined(separator: ", ") + output.append("DNS = \(dnsString)\n") + } + if let mtu = interface.mtu { + output.append("MTU = \(mtu)\n") + } + + for peer in peers { + output.append("\n[Peer]\n") + output.append("PublicKey = \(peer.publicKey.base64Key)\n") + if let preSharedKey = peer.preSharedKey?.base64Key { + output.append("PresharedKey = \(preSharedKey)\n") + } + if !peer.allowedIPs.isEmpty { + let allowedIPsString = peer.allowedIPs.map { $0.stringRepresentation }.joined(separator: ", ") + output.append("AllowedIPs = \(allowedIPsString)\n") + } + if let endpoint = peer.endpoint { + output.append("Endpoint = \(endpoint.stringRepresentation)\n") + } + if let persistentKeepAlive = peer.persistentKeepAlive { + output.append("PersistentKeepalive = \(persistentKeepAlive)\n") + } + } + + return output + } + + private static func collate(interfaceAttributes attributes: [String: String]) throws -> InterfaceConfiguration { + guard let privateKeyString = attributes["privatekey"] else { + throw ParseError.interfaceHasNoPrivateKey + } + guard let privateKey = PrivateKey(base64Key: privateKeyString) else { + throw ParseError.interfaceHasInvalidPrivateKey(privateKeyString) + } + var interface = InterfaceConfiguration(privateKey: privateKey) + if let listenPortString = attributes["listenport"] { + guard let listenPort = UInt16(listenPortString) else { + throw ParseError.interfaceHasInvalidListenPort(listenPortString) + } + interface.listenPort = listenPort + } + if let addressesString = attributes["address"] { + var addresses = [IPAddressRange]() + for addressString in addressesString.splitToArray(trimmingCharacters: .whitespacesAndNewlines) { + guard let address = IPAddressRange(from: addressString) else { + throw ParseError.interfaceHasInvalidAddress(addressString) + } + addresses.append(address) + } + interface.addresses = addresses + } + if let dnsString = attributes["dns"] { + var dnsServers = [DNSServer]() + var dnsSearch = [String]() + for dnsServerString in dnsString.splitToArray(trimmingCharacters: .whitespacesAndNewlines) { + if let dnsServer = DNSServer(from: dnsServerString) { + dnsServers.append(dnsServer) + } else { + dnsSearch.append(dnsServerString) + } + } + interface.dns = dnsServers + interface.dnsSearch = dnsSearch + } + if let mtuString = attributes["mtu"] { + guard let mtu = UInt16(mtuString) else { + throw ParseError.interfaceHasInvalidMTU(mtuString) + } + interface.mtu = mtu + } + return interface + } + + private static func collate(peerAttributes attributes: [String: String]) throws -> PeerConfiguration { + guard let publicKeyString = attributes["publickey"] else { + throw ParseError.peerHasNoPublicKey + } + guard let publicKey = PublicKey(base64Key: publicKeyString) else { + throw ParseError.peerHasInvalidPublicKey(publicKeyString) + } + var peer = PeerConfiguration(publicKey: publicKey) + if let preSharedKeyString = attributes["presharedkey"] { + guard let preSharedKey = PreSharedKey(base64Key: preSharedKeyString) else { + throw ParseError.peerHasInvalidPreSharedKey(preSharedKeyString) + } + peer.preSharedKey = preSharedKey + } + if let allowedIPsString = attributes["allowedips"] { + var allowedIPs = [IPAddressRange]() + for allowedIPString in allowedIPsString.splitToArray(trimmingCharacters: .whitespacesAndNewlines) { + guard let allowedIP = IPAddressRange(from: allowedIPString) else { + throw ParseError.peerHasInvalidAllowedIP(allowedIPString) + } + allowedIPs.append(allowedIP) + } + peer.allowedIPs = allowedIPs + } + if let endpointString = attributes["endpoint"] { + guard let endpoint = Endpoint(from: endpointString) else { + throw ParseError.peerHasInvalidEndpoint(endpointString) + } + peer.endpoint = endpoint + } + if let persistentKeepAliveString = attributes["persistentkeepalive"] { + guard let persistentKeepAlive = UInt16(persistentKeepAliveString) else { + throw ParseError.peerHasInvalidPersistentKeepAlive(persistentKeepAliveString) + } + peer.persistentKeepAlive = persistentKeepAlive + } + return peer + } + +} diff --git a/Sources/TunnelKitWireGuardCore/WireGuard.swift b/Sources/TunnelKitWireGuardCore/WireGuard.swift new file mode 100644 index 0000000..d7dc272 --- /dev/null +++ b/Sources/TunnelKitWireGuardCore/WireGuard.swift @@ -0,0 +1,29 @@ +// +// WireGuard.swift +// TunnelKit +// +// Created by Davide De Rosa on 11/21/21. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of TunnelKit. +// +// TunnelKit is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// TunnelKit is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with TunnelKit. If not, see . +// + +import Foundation + +public class WireGuard { +} diff --git a/Sources/TunnelKitWireGuardManager/WireGuardProvider+Configuration.swift b/Sources/TunnelKitWireGuardManager/WireGuardProvider+Configuration.swift new file mode 100644 index 0000000..a9e9f47 --- /dev/null +++ b/Sources/TunnelKitWireGuardManager/WireGuardProvider+Configuration.swift @@ -0,0 +1,79 @@ +// +// WireGuardProvider+Configuration.swift +// TunnelKit +// +// Created by Davide De Rosa on 11/21/21. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of TunnelKit. +// +// TunnelKit is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// TunnelKit is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with TunnelKit. If not, see . +// + +import Foundation +import NetworkExtension +import TunnelKitManager +import TunnelKitWireGuardCore +import WireGuardKit + +extension WireGuardProvider { + public struct Configuration { + public let innerConfiguration: WireGuard.Configuration + + // required by WireGuardTunnelProvider + public var tunnelConfiguration: TunnelConfiguration { + return innerConfiguration.tunnelConfiguration + } + + public init(innerConfiguration: WireGuard.Configuration) { + self.innerConfiguration = innerConfiguration + } + + private init(wgQuickConfig: String) throws { + innerConfiguration = try WireGuard.Configuration(wgQuickConfig: wgQuickConfig) + } + + public func generatedTunnelProtocol(withBundleIdentifier bundleIdentifier: String, appGroup: String, context: String) throws -> NETunnelProviderProtocol { + + let protocolConfiguration = NETunnelProviderProtocol() + protocolConfiguration.providerBundleIdentifier = bundleIdentifier + protocolConfiguration.serverAddress = innerConfiguration.endpointRepresentation + + let keychain = Keychain(group: appGroup) + let wgString = innerConfiguration.asWgQuickConfig() + protocolConfiguration.passwordReference = try keychain.set(password: wgString, for: "", context: context) + protocolConfiguration.providerConfiguration = ["AppGroup": appGroup] + + return protocolConfiguration + } + + public static func appGroup(from protocolConfiguration: NETunnelProviderProtocol) throws -> String { + guard let appGroup = protocolConfiguration.providerConfiguration?["AppGroup"] as? String else { + throw WireGuardProviderError.savedProtocolConfigurationIsInvalid + } + return appGroup + } + + public static func parsed(from protocolConfiguration: NETunnelProviderProtocol) throws -> Configuration { + guard let passwordReference = protocolConfiguration.passwordReference, + let wgString = try? Keychain.password(forReference: passwordReference) else { + + throw WireGuardProviderError.savedProtocolConfigurationIsInvalid + } + return try Configuration(wgQuickConfig: wgString) + } + } +} diff --git a/Sources/TunnelKitWireGuardManager/WireGuardProvider.swift b/Sources/TunnelKitWireGuardManager/WireGuardProvider.swift new file mode 100644 index 0000000..98a3d1f --- /dev/null +++ b/Sources/TunnelKitWireGuardManager/WireGuardProvider.swift @@ -0,0 +1,74 @@ +// +// WireGuardProvider.swift +// TunnelKit +// +// Created by Davide De Rosa on 11/21/21. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of TunnelKit. +// +// TunnelKit is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// TunnelKit is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with TunnelKit. If not, see . +// + +import Foundation +import NetworkExtension +import TunnelKitManager + +public class WireGuardProvider: VPNProvider { + private let provider: NetworkExtensionVPNProvider + + public init(bundleIdentifier: String) { + provider = NetworkExtensionVPNProvider(locator: NetworkExtensionTunnelLocator(bundleIdentifier: bundleIdentifier)) + } + + // MARK: VPNProvider + + public var isPrepared: Bool { + return provider.isPrepared + } + + public var isEnabled: Bool { + return provider.isEnabled + } + + public var status: VPNStatus { + return provider.status + } + + public func prepare(completionHandler: (() -> Void)?) { + provider.prepare(completionHandler: completionHandler) + } + + public func install(configuration: VPNConfiguration, completionHandler: ((Error?) -> Void)?) { + provider.install(configuration: configuration, completionHandler: completionHandler) + } + + public func connect(completionHandler: ((Error?) -> Void)?) { + provider.connect(completionHandler: completionHandler) + } + + public func disconnect(completionHandler: ((Error?) -> Void)?) { + provider.disconnect(completionHandler: completionHandler) + } + + public func reconnect(configuration: VPNConfiguration, delay: Double? = nil, completionHandler: ((Error?) -> Void)?) { + provider.reconnect(configuration: configuration, delay: delay, completionHandler: completionHandler) + } + + public func uninstall(completionHandler: (() -> Void)?) { + provider.uninstall(completionHandler: completionHandler) + } +} diff --git a/Sources/TunnelKitWireGuardManager/WireGuardProviderError.swift b/Sources/TunnelKitWireGuardManager/WireGuardProviderError.swift new file mode 100644 index 0000000..9e05a9c --- /dev/null +++ b/Sources/TunnelKitWireGuardManager/WireGuardProviderError.swift @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +// Copyright © 2018-2021 WireGuard LLC. All Rights Reserved. + +import Foundation + +public enum WireGuardProviderError: String, Error { + case savedProtocolConfigurationIsInvalid + case dnsResolutionFailure + case couldNotStartBackend + case couldNotDetermineFileDescriptor + case couldNotSetNetworkSettings +}