Network Extension Setup
Last updated
Was this helpful?
Last updated
Was this helpful?
Overview
A network extension is a separate process that runs alongside your main application and handles the VPN connection. This step involves creating a new target in your Xcode project, configuring its build settings, and implementing the necessary code to establish and manage the VPN connection.
You should already have prepared application target in order to continue. If you haven't done it yet, please see Application Setup.
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 type ‘Network’ into the search bar then click Network Extension
.
Provide the following for this Network Extension target: name, bundle ID (if needed) and change Provider Type to “Packet Tunnel”. Then click finish.
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.companyname.myapp
Network extension target: MyApp Hydra Provider, com.companyname.myapp.hydraprovider
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.
Link frameworks:
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
under Embed
option for HydraTunnelProvider.framework.
In the SDK folder, the HydraTunnelProvider.xcframework
file in your downloads folder with in the VPNSDK x.x.x
(for example, VPNSDK 6.4.0
) folder. Go to Project -> Network Extension Target -> General and drag copied framework to Frameworks, Libraries and Embedded Content section.
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
under Embed and sign
option for WireguardTunnelProvider.framework.
To the Network Extension target, click the ‘+’ button, search for libz.tbd, and add it. Click the ‘+’ button again, search for libresolv.tbd, and add it.
Go to Project -> Network Extension Target -> Build Settings and:
Set Enable Bitcode to NO;
Add -ObjC
to Other Linker Flags.
Select your Network Target
Select ‘All’ in the ribbon just under the ribbon with ‘General, Signing & Capabilities … Build Settings’
Search “Other Linker Flags” in the search bar on the top right
Select the + button next to Debug, type in ‘-ObjC’ (case sensitive) into the box and hit enter
Select the + button next to Release, type in ‘-ObjC’ (case sensitive) into the box and hit enter
Note that Bitcode is deprecated.
The instructions for configuring our SDK with IPSec on iOS/macOS can be found on the IPSEC VPN SDK for iOS/macOS.
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.
Make this class implement BaseNetworkExtensionDelegate
instead of NEPacketTunnelProvider
. It should now look like:
For Hydra Protocol
For Wireguard Protocol
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.
In Xcode, a plist (short for property list) is a structured data format used to store and manage application settings, configuration data, and other key-value pairs in macOS and iOS applications. Plist files use XML or binary format to represent a hierarchical data structure, which can include dictionaries, arrays, strings, numbers, dates, and boolean values.
Navigate to your root project, click on your Application Target (the top of the target list), then click ‘Info’ in the settings ribbon at the top of the page
Go to the ‘URL Types (0)’ section at the bottom of the page
Expand the section and then click the ‘+’ button
The section will populate with a icon that says “No Image Specified” and a few drop down menus. Leave these alone.
On the left in the project navigator section of Xcode, a new ‘Info’ file will appear
This box will appear after hitting the ‘+’ button, you can leave this alone
Staying in Network Extension target, set NSExtensionPrincipalClass
in NSExtension
dictionary of Info.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 named ProviderDelegate
, then the value would be $(PRODUCT_MODULE_NAME).ProviderDelegate
.
Read more about Creating a Packet Tunnel Provider Extension from Apple docs.
Right click the new Info file select Open As > Source Code
To properly configure your Network Extension target, it is essential to set the NSExtensionPrincipalClass
and NetworkExtensionDelegate
in the Info.plist file. These configurations ensure that the correct tunnel provider and delegate classes are used, enabling the functionality of your network extension.
Create a new line #9 so that is on line #8 and is on line #10
Paste the following code snippet into the blank line #9:
Note the commented out code on lines #14, 15 and 16. You will need to uncomment the line which corresponds to the VPN protocol that you will be using. You can leave the unused protocol line either commented out or delete it all together.
Next you need to perform all needed setup on Apple 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, IDs & 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
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.
Please note that one of the steps within the Configuring App Groups will ask you to input your Team ID. For more details, see Locate Your Team ID.
You need to assign this group to both, the Application and the Network Extension targets and App IDs.
For both, Application and Network Extension targets, go to Project -> Target -> Capabilities and enable the following capabilities:
Access WiFi Information
Network Extensions
Packet Tunnel
Personal VPN
App Groups
For macOS targets, enable Keychain Sharing capability with your Group ID
Make sure that respective .entitlement files are added to the project for both targets.
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.
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.
If you're using macOS Catalina (10.15) or later, you can use Finder to obtain the UDID.
Connect your iPhone or iPad to your Mac using a USB cable.
Open a Finder window.
In the left sidebar under "Locations," your connected device should appear. Click on the device's name.
You'll see general information about your device, such as its name, storage capacity, and software version.
Click on the device's serial number. It will change to display the UDID. You can right-click the UDID to copy it for easy pasting into the Apple Developer Portal.
If you're using macOS Mojave (10.14) or earlier, or a Windows PC, you'll use iTunes to obtain the UDID.
Connect your iPhone or iPad to your computer using a USB cable.
Launch iTunes if it doesn’t open automatically.
In iTunes, click on the device icon located near the top-left corner of the window. This will open the Summary page for your device.
On the Summary page, you’ll see information about your device, including its serial number.
Click on the serial number, and it will change to display the UDID. You can right-click the UDID to copy it for easy pasting into the Apple Developer Portal.
If you have Xcode installed, you can also use it to obtain the UDID.
Connect your iPhone or iPad to your Mac using a USB cable.
Launch Xcode.
In Xcode, go to the menu bar and click on Window > Devices and Simulators.
Under the Devices tab, you'll see your connected device listed on the left side. Click on the device’s name.
The UDID will be displayed under the Identifier label in the details panel on the right. You can select and copy it.
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 to No
.
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
.
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.
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)