Network Extension Setup
Network extension setup
You should already have prepared application target in order to continue, if you haven't done it yet, please check this.
Create network extension target
You need to create network extension in order to use Hydra and WireGuard protocols.
Go to Project -> Targets, and in menu bar select Editor > Add Target. Select needed platform (iOS or macOS), then choose Network Extension type, provide the name and bundle ID for this Network Extension target.
NOTE: It is recommended to give distinctive names to your targets and bundle IDs with mention of target protocol, e.g. for Hydra:
Application target: MyApp, com.blabla.myapp
Network extension target: MyApp Hydra Provider, com.blabla.myapp.hydraprovider
Install tunnel provider SDK
At this point you have to have at least two targets:
Application target
Network Extension target
Now you should link tunnel provider SDK to the Network Extension target. We're providing SDK packed as xcframework
, which means it can be used both for iOS and macOS apps.
Manual
Link frameworks:
Hydra
Copy HydraTunnelProvider.xcframework file to some place inside your project folder on disk.
Go to Project -> Network Extension Target -> General and drag copied framework to Frameworks, Libraries and Embedded Content section.
Set
Do Not Embed
underEmbed and sign
option for HydraTunnelProvider.framework.
WireGuard
Copy WireguardTunnelProvider.framework file to some place inside your project folder on disk.
Go to Project -> Network Extension Target -> General and drag copied framework to Frameworks, Libraries and Embedded Content section.
Set
Do Not Embed
underEmbed and sign
option for WireguardTunnelProvider.framework.
Link NetworkExtension system framework to the Network Extension target.
Link libz.tbd and libresolv.tbd libraries to the Network Extension target.
Go to Project -> Network Extension Target -> Build Settings and:
Set Enable Bitcode to NO;
Add
-ObjC
to Other Linker Flags.
Conform to Network Extension delegate
After the Network Extension target is created, you should observe that new class is added to your project (file PacketTunnelProvider.swift). Go to the PacketTunnelProvider.swift, rename it to ProviderDelegate and make this class implement BaseNetworkExtensionDelegate
instead of NEPacketTunnelProvider
. It should now look like:
Remove Xcode-generated empty PacketTunnelProvider
's implementation. Now you can implement needed methods from BaseNetworkExtensionDelegate. Also, if you want to use Fireshield related methods in network extension you can make your ProviderDelagate class conform to FireshieldNetworkExtensionDelegate protocol which extends base delegate. Pay attention that it makes sense only if you're using Hydra protocol, otherwise Fireshield methods won't be called.
Setup Info.plist
Staying in Network Extension target, set
NSExtensionPrincipalClass
inNSExtension
dictionary ofInfo.plist
to corresponding value depending on protocol:
Hydra:
AFHydraTunnelProvider
WireGuard:
AFWireGuardTunnelProvider
Add new key to a plist root:
NetworkExtensionDelegate
with a value that is your provider delegate class from the previous step. For example, if your class namedProviderDelegate
, then the value would be$(PRODUCT_MODULE_NAME).ProviderDelegate
.
Read more about Creating a Packet Tunnel Provider Extension from Apple docs.
Setup App ID
Next you need to perform all needed setup on Apple developer portal.
Setup on developer portal
You should already have app ID for Application target, now you need another one for Network Extension target. Go to Apple developer portal->Certificates, Identifiers & Profiles->Identifiers and add new identifier for your Network Extension. Turn on following capabilities for both app IDs (Application and Network Extension):
Access WiFi Information
App Groups
Network Extensions
Personal VPN
Create App Group
Since HydraSDK is mostly a Network Extension you also have to create an App Group and provide group ID to the SDK to allow Hydra to interact with Packet Tunnel Provider Extension. See Configuring App Groups for more information about how to create app group.
You need to assign this group to both, the Application and the Network Extension targets and App IDs.
Turn on capabilities in project
For both, Application and Network Extension targets, go to Project -> Target -> Capabilities and enable the following capabilities:
Access WiFi Information
App Groups
Network Extensions
Packet Tunnel
Personal VPN
For macOS targets, enable Keychain Sharing capability with your Group ID
NOTE: Make sure that respective .entitlement files are added to the project for both targets.
Re/Generate Provision Profiles
Application and Network Extension, both have to have its respective Provision Profiles generated from the Developer Portal. When creating and/or regenerating Provision Profiles, make sure you select Network Extension entitlement.
NOTE: The Provision Profiles' entitlements must corresponds to entitlements configured through Xcode's project Capabilities tab. If there is a missconfiguration between the two, VPN connection will not be established.
Integration Checklist
Checklist that should help you to verify correct integration:
Network Extension
Ensure it is created
Frameworks
VPNApplicationSDK.framework
is added to the Application target.HydraTunnelProvider.framework
is added to the Extension target (for Hydra).WireguardTunnelProvider.framework
is added to the Extension target (for WireGuard)
Libraries
libz.tbd
and libresolv.tbd
are added to the Extension target
Linker Flags
In
User-Defined
,ENABLE_BITCODE
is set toNo
.In
Linking-General
,Other Linker Flags
is set to-ObjC
.
App Groups
You have created and enabled App Groups (General > Capabilities) for both targets, active App Group is set to "builder.groupId" (App Groups is enabled for both bundle ids (Application and Extension) in Apple Developer Portal).
Personal VPN
Personal VPN (General > Capabilities) is enabled for both targets (Personal VPN is enabled for both bundle ids (Application and Extension) in Apple Developer Portal).
Entitlements
You have added Network Extension (iOS) entitlement for both Application and Extension provisioning profiles.
SDK Configuration
SDK instance is configured with correct groupData
and extensionBundleID
.
Troubleshooting
The bundle identifier of the embedded binary does not have the parent application's bundle identifier as a prefix.
To resolve this:
Log in to your Apple Developer account and navigate to the "Certificates, Identifiers & Profiles" section.
Remove the existing Identifiers and Profiles associated with the embedded extensions of your app.
You do not need to remove the main app identifier, only the extension identifiers.
Create new Identifiers and Profiles for the extensions you removed in the previous step. Ensure that the bundle identifiers for the new Identifiers are properly prefixed with the parent app's bundle identifier.
Open your Xcode project and navigate to the "Signing & Capabilities" tab for each of the affected targets (i.e., the extensions).
Under the "Provisioning Profile" section, click on the "Download Profile" button to download the new Profiles you created in step 3.
Select the appropriate downloaded Provisioning Profile for each target.
Clean and rebuild your project.
Xcode won’t pause at this breakpoint because it has not been resolved
When you're developing an app extension, such as a PacketTunnelProvider
, and you find that Xcode won't pause at your breakpoints, you might see the following message:
Follow these steps to resolve the issue and get your breakpoints working again:
In Xcode, clean and rebuild your project. Enable the VPN connection within the app.
Click on Debug in the menu bar, then select Attach to Process by PID or Name….
In the dialog that appears, enter the name of your extension target. For example,
VPNSDK Demo Hydra Provider
, type that into the field. Keep in mind that your app and extension run as separate processes, so be sure to attach to the correct one.Once you've selected the correct process, click the Attach button.
You should now see breakpoint highlighted, indicating it is active.
It's important to note that if you want to set a breakpoint in start lifecycle methods (such as vpnWillStart
), you need to attach the debugger before connecting to the VPN. Otherwise, these methods will have already been called by the time you attach, and the breakpoint will not be hit.
If Xcode seems to be stuck while waiting to attach to your extension process, please ensure that:
Your app is already running
The VPN connection is active (VPN icon is visible in the status bar)
Last updated