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, which in turn enables support for a certain range of encryption and digest algorithms.
The client is known to work with OpenVPN® 2.3+ servers.
- Handshake and tunneling over UDP or TCP
- AES-CBC (128/192/256 bit)
- AES-GCM (128/192/256 bit, 2.4)
- HMAC digests
- SHA-2 (224/256/384/512 bit)
- NCP (Negotiable Crypto Parameters, 2.4)
- TLS handshake
- Server validation (CA, EKU)
- Client certificate
- TLS wrapping
- Authentication (
- Encryption (
- Authentication (
- Compression framing
--comp-lzo(deprecated in 2.4)
- Compression algorithms
- LZO (via
- LZO (via
- Key renegotiation
- Replay protection (hardcoded window)
The library therefore supports compression framing, just not newer compression. Remember to match server-side compression and framing, otherwise the client will shut down with an error. E.g. if server has
comp-lzo no, client must use
compressionFraming = .compLZO.
Support for .ovpn configuration
TunnelKit can parse .ovpn configuration files. Below are a few details worth mentioning.
- Single-byte XOR masking
--scramble xormask <character>
- XOR all incoming and outgoing bytes by the ASCII value of the character argument
- See Tunnelblick website for more details
- UDP fragmentation, i.e.
- Compression via
--compressother than empty or
- Connecting via proxy
- External file references (inline
- Static key encryption (non-TLS)
net_gatewayliterals in routes
- Some MTU overrides
hostvalues (first wins)
- Static client-side routes
Many other flags are ignored too but it's normally not an issue.
- iOS 12.0+ / macOS 10.15+
- Xcode 11+ (Swift 5)
- Git (preinstalled with Xcode Command Line Tools)
- Ruby (preinstalled with macOS)
- CocoaPods 1.6.0
- jazzy (optional, for documentation)
- Disable Bitcode
It's highly recommended to use the Git and Ruby packages provided by Homebrew.
To use with CocoaPods just add this to your Podfile:
Download the library codebase locally:
$ git clone https://github.com/passepartoutvpn/tunnelkit.git
Assuming you have a working CocoaPods environment, setting up the library workspace only requires installing the pod dependencies:
$ pod install
After that, open
TunnelKit.xcworkspace in Xcode and run the unit tests found in the
TunnelKitTests folder. A simple CMD+U while on
TunnelKit-(iOS|macOS) should do that as well.
There are demo targets containing a simple app for testing the tunnel, called
For the VPN to work properly, the
BasicTunnel demo requires:
- App Groups and Keychain Sharing capabilities
- App IDs with Packet Tunnel entitlements
both in the main app and the tunnel extension target.
In order to test connectivity in your own environment, modify the file
TunnelKit/Demo/Configuration.swift to match your VPN server parameters.
private let ca = CryptoContainer(pem: """ -----BEGIN CERTIFICATE----- MIIFJDCC... -----END CERTIFICATE----- """)
Make sure to also update the following constants in the same files, according to your developer account and your target bundle identifiers:
public static let appGroup public static let tunnelIdentifier
Remember that the App Group on macOS requires a team ID prefix.
The library is split into several modules, in order to decouple the low-level protocol implementation from the platform-specific bridging, namely the NetworkExtension VPN framework.
Full documentation of the public interface is available and can be generated with jazzy. After installing the jazzy Ruby gem with:
$ gem install jazzy
enter the root directory of the repository and run:
The generated output is stored into the
docs directory in HTML format.
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)
There are no physical network implementations (e.g. UDP or TCP) in this module.
Provides a layer on top of the NetworkExtension framework. Most importantly, bridges native NWUDPSession and NWTCPConnection to an abstract
GenericSocket interface, thus making a multi-protocol VPN dramatically easier to manage.
This subspec includes convenient classes to control the VPN tunnel from your app without the NetworkExtension headaches. Have a look at
MockVPNProvider(default, useful to test on simulator)
Here you find
NativeProvider, a generic way to manage a VPN profile based on the native IPSec/IKEv2 protocols. Just wrap a
NEVPNProtocolIKEv2 object in a
NetworkExtensionVPNConfiguration and use it to install or connect to the VPN.
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 module depends on OpenSSL.
The entry point is the
OpenVPNSession class. The networking layer is fully abstract and delegated externally with the use of opaque
Another goal of this module is packaging up a black box implementation of a NEPacketTunnelProvider, which is the essential part of a Packet Tunnel Provider app extension. You will find the main implementation in the
OpenVPNTunnelProvider class. On the client side, you manage the VPN profile with the
OpenVPNProvider class, which is a specific implementation of
A debug log snapshot is optionally maintained and shared by the tunnel provider to host apps via the App Group container.
Due to the restrictive license (GPLv2), LZO support is provided as an optional subspec.
Copyright (c) 2020 Davide De Rosa. All rights reserved.
This project is licensed under the GPLv3.
As seen in libsignal-protocol-c:
Additional Permissions For Submission to Apple App Store: Provided that you are otherwise in compliance with the GPLv3 for each covered work you convey (including without limitation making the Corresponding Source available in compliance with Section 6 of the GPLv3), the Author also grants you the additional permission to convey through the Apple App Store non-source executable versions of the Program as incorporated into each applicable covered work as Executable Versions only under the Mozilla Public License version 2.0 (https://www.mozilla.org/en-US/MPL/2.0/).
Part I and II do not apply to the LZO library, which remains licensed under the terms of the GPLv2+.
By contributing to this project you are agreeing to the terms stated in the Contributor License Agreement (CLA).
For more details please see CONTRIBUTING.
- lzo - Copyright (c) 1996-2017 Markus F.X.J. Oberhumer
- PIATunnel - Copyright (c) 2018-Present Private Internet Access
- SwiftyBeaver - Copyright (c) 2015 Sebastian Kreutzberger
- XMB5 for the XOR patch - Copyright (c) 2020 Sam Foxman
This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (https://www.openssl.org/)
Copyright (c) 2002-2018 OpenVPN Inc. - OpenVPN is a registered trademark of OpenVPN Inc.