Using SimpleTunnel's PacketProvider app extension to test per-app capabilities

So Im trying to build a MacOS per-app vpn client to test out the Network Extensions API. I plan to use a configuration profile to both configure the per app vpn and to configure apps to work with the per app vpn along with my own custom protocol in PacketTunnelProvider app extension. Originally, in my PacketTunnelProvider app extension, I was trying to recreate my own IKEv2 custom protocol, but Ive realized I dont nessearily need to do that to test my client app. Instead, I could do something similar to the SimpleTunnnel example which simply creates a TCP connection to the server.


My question is:

Can I use the PacketTunnel app extension, SimpleTunnelServices, and tunel_server (to create the server) code in my per-app vpn project?

Or are there any restrictions that might prevent that example code from working in a per-app vpn basis?

Replies

The major gotcha you’ll encounter here is in

tunnel_server
, which is unable to route traffic off the Mac on which it’s running. That’s a serious restriction for folks trying to do general VPN work, but in your case it may be OK because you’re working with per-app VPN, and it’s reasonable to run the services that the selected apps are talking to on the Mac running
tunnel_server
.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks! Related to this, I seem to be having problems loading the per-app vpn config I created with a configuration profile when I use the method "loadAllFromPreferences" in my app project. When I install the configuration profile into the computer, I can see the VPN appear in "Network Preferences." Other vpns I programatically create in my app do seem to load when I call the method "loadAllFromPreferences" and also appear in "Network Preferences" so Im thinking it might have to do with my per app vpn configuration profile.


The following is my vpn paylaod content:

<dict>
     <key>PayloadUUID</key>
     <string>2578BBF3-1507-4DF2-B091-xxxxxxxxxxxx</string>
     <key>PayloadType</key>
     <string>com.apple.vpn.managed.applayer</string>
     <key>PayloadIdentifier</key>
     <string>com.apple.vpn.managed.6854115B-3233-4556-B087-xxxxxxxxxxxx</string>
     <key>VPNType</key>
     <string>VPN</string>
     <key>VPNSubType</key>  
     <string>App Extension Bundle ID Here</string>
     <key>UserDefinedName</key>  
     <string>Configured Per App VPN</string>
     <key>PayloadDescription</key>
     <string>Configures settings for Per-App VPN</string>
     <key>PayloadDisplayName</key>
     <string>Per-App VPN</string>
     <key>PayloadVersion</key>
     <integer>1</integer>
     <key>VPNUUID</key>  
     <string>E81B2971-09E0-4DB7-8526-xxxxxxxxxxxx</string>
     <key>VPN</key>  
     <dict>  
          <key>RemoteAddress</key>  
          <string>website.com</string> 
          <key>AuthenticationMethod</key>  
          <string>Password</string>  
          <key>AuthName</key>  
          <string>username1</string>  
          <key>AuthPassword</key>  
          <string>password1</string>
          <key>OnDemandMatchAppEnabled</key>
          <true/>
          <key>ProviderType</key>
          <string>packet-tunnel</string>
     </dict> 
     <key>SafariDomains</key>  
     <array>  
          <string>google.com</string>  
     </array>
</dict>



Any thoughts on the possible issue?

The most likely cause of this problem is bundle identifiers. You wrote:

<key>VPNSubType</key>
<string>App Extension Bundle ID Here</string>

I’m going to presume you used a real value here, and this placeholder is just for the sake of your DevForums post. However, you seem to be mixed up on the expected value, namely:

  • VPNSubType
    should be the bundle identifier of the host app
  • VPN
    >
    ProviderBundleIdentifier
    should be the bundle identifier of the provider within that host app.

At the end of this response you’ll find the payload that I use for one of my test apps.

IMPORTANT This is an app proxy provider rather than a packet tunnel provider, and thus doesn’t have the

ProviderType
property. When you want to run a packet tunnel provider in per-app mode, you must include that key with the value
packet-tunnel
, as shown by your example.

Finally, be aware that a lot of the properties in this list are optional, and they’re only present here because I created the initial configuration profile using Apple Configurator, and it’s rather enthusiastic about including optional properties.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
<dict>
    <key>PayloadUUID</key>
    <string>944561DB-AEAD-43FA-8DC0-F8661BF5CC9A</string>
    <key>PayloadType</key>
    <string>com.apple.vpn.managed.applayer</string>
    <key>PayloadIdentifier</key>
    <string>com.apple.vpn.managed.applayer.7EDB76A2-ADFC-4D2B-8831-0BA2B1C75579</string>
    <key>VPNType</key>
    <string>VPN</string>
    <key>VPNSubType</key>
    <string>com.example.apple-samplecode.QNEAppProxy-macOS</string>
    <key>UserDefinedName</key>
    <string>QNEAppProxy</string>
    <key>PayloadDescription</key>
    <string>Configures VPN settings</string>
    <key>PayloadDisplayName</key>
    <string>VPN</string>
    <key>PayloadVersion</key>
    <integer>1</integer>
    <key>VPNUUID</key>
    <string>83A8720B-2BD5-4B7E-921D-3D9E312B4ACD</string>
    <key>VPN</key>
    <dict>
        <key>RemoteAddress</key>
        <string>example.com</string>
        <key>AuthenticationMethod</key>
        <string>Password</string>
        <key>AuthName</key>
        <string>mrgumby</string>
        <key>AuthPassword</key>
        <string>opendoor</string>
        <key>ProviderBundleIdentifier</key>
        <string>com.example.apple-samplecode.QNEAppProxy-macOS.Provider</string>
        <key>OnDemandMatchAppEnabled</key>
        <true/>
    </dict>
    <key>Proxies</key>
    <dict>
        <key>HTTPEnable</key>
        <integer>0</integer>
        <key>HTTPSEnable</key>
        <integer>0</integer>
    </dict>
    <key>SafariDomains</key>
    <array>
        <string>httpbin.org</string>
    </array>
</dict>

Awesome! This seemed to work.


Lastly, is there a way to view NSLogs outputted by the app extension? Ive seen other forums describing how to do it from an IOS device or simulator but since I am using the app extension on a MacOS app, then neither of those answers help.

Lastly, is there a way to view NSLogs outputted by the app extension?

You can do this using macOS’s Console app:

  1. Connect the iOS device to the Mac via USB.

  2. Run Console.

  3. Select the iOS device on the left.

  4. Marvel at the amount of glorious debugging information you have access to!

Step 4 can be a bit of a problem, in that your logging tends to get lost amongst all the system logging. You need to learn to love Console’s filtering features. If you’re using

NSLog
, it’s best to put some standard string in your log messages (I used
QQQ
) so you can filter on that. However, I only do this for small test projects. In a production-quality app I strongly recommend that you use the OS log API (
<os/log.h>
). This lets you assign category and subsystem identifiers to your log entries, which radically improves your Console filtering experience.

To learn more about the OS log API, watch WWDC 2016 Session 721 Unified Logging and Activity Tracing.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Dear Eskimo,


Greetings !!


with my folding hands I am also here 🙂


PacketTunnelProvider PER - APP is Executed with CUSTOM SSL Server in :-

Created App + Configuration Profile (loaded with CUSTOM SSL Server & provider type tunnel not proxy ) + loaded on iPad + run the App with extenssion and it's connected with UBANTU CUSTOM SSL Server .


but now I want to connect it with IKEV2 Server rather than custom SSL vpn server where i am failed .

Same App + Configuration Profile (updated with IKEV2 Server Info & provider type tunnel not proxy ) + loaded on iPad + run the App with extenssion and it's not connected with IKEV2 Server.





May you help me there ??