I am developing a VPN app for iOS using Xamarin. As per iOS docs there needs to be an app extension which would finally connect VPN to a remote server.
Question 1. Can I create an app extension supporting 'Packet Tunnel' in Xamarin on Mac OS X using Visual Studio code. When I try to create an app extension in the wizard there is no VPN extension option. I created an Action Sheet extension and manually modified Info.plist and Entitlement.plist file to support VPN a hack.
With above changes I was able to create an app extension and was able to deploy on a real device. ow the main iOS app was able to save VPN profile and I could see it in settings. My current app extension tunnel provider class is empty I just have simple log lines.
Question 2. I was expecting I would get some logs and it would eventually fail as there is no code, but my class is never called. There is no stacktrace. Only thing I could extract from console connecting to real device is as follows.
Unhandled Exception:
Foundation.MonoTouchException: Objective-C exception thrown. Name: NSInvalidArgumentException Reason: *** -[__NSDictionaryM setObject:forKey:]: object cannot be nil (key: 7E3DD3B9-285A-4EB1-9DCA-6EC5B89214DA)
Native stack trace:
0 CoreFoundation 0x00000001b130a9a4 <redacted> 252
1 libobjc.A.dylib 0x00000001b04e39f8 objc_exception_throw 56
2 CoreFoundation 0x00000001b12843f8 _CFArgv 0
3 CoreFoundation 0x00000001b11f9228 <redacted> 940
4 Foundation 0x00000001b1d288b4 <redacted> 100
5 Foundation 0x00000001b1d28124 <redacted> 764
6 libdispatch.dylib 0x00000001b0d48a38 <redacted> 24
7 libdispatch.dylib 0x00000001b0d497d4 <redacted> 16
8 libdispatch.dylib 0x00000001b0cf2324 <redacted> 592
9 libdispatch.dylib 0x00000001b0cf2e40 <redacte<…>
I am starting tunnel as follows. The below code is inside NETunnelProviderManager.LoadAllFromPreferences completion handler.
var activationAttemptId = new NSUuid().AsString() "-SECRET-VPN";
Console.WriteLine("Activation UUID " activationAttemptId);
var options = new NSDictionary<NSString, NSObject>((NSString)NSObject.FromObject("activationAttemptId"), NSObject.FromObject(activationAttemptId));
var sessionConnection = tunnelProviderManager.Connection as NETunnelProviderSession;
NSError terror;
sessionConnection.StartTunnel(options, out terror);
if (terror != null && terror.Code != null)
{
Console.Error.WriteLine("While starting VPN error ...." terror.Code);
}
My configuration saving code is as follows.
var tunnelProviderManager = new NETunnelProviderManager();
tunnelProviderManager.LocalizedDescription = "Second Xam VPN";
var protocolConfiguration = new NETunnelProviderProtocol();
protocolConfiguration.ProviderBundleIdentifier = "xxx.xxx";
protocolConfiguration.ServerAddress = "XXX:XXX";
protocolConfiguration.ProviderConfiguration = new NSDictionary<NSString, NSObject>();
tunnelProviderManager.ProtocolConfiguration = protocolConfiguration;
tunnelProviderManager.Enabled = true;
tunnelProviderManager.SaveToPreferences((NSError error) => {// ...logic here .....});
I'll really appreciate If some guidance is provided how to tackle the issue may be some debug help, I have intermediate skills with Xamarin and overall mobile development.
Both apps and apps extension Info.plist and Entitlement.plist have correct entitlements.
One thing would like to share Visual Studio for Mac 2019 adds incorrect entitlement when graphical editor is used. It adds value for key com.apple.developer.networking.networkextension as packet-tunnel instead of packet-tunnel-provider.
CodePudding user response:
Two issues.
I still do not agree the value for key com.apple.developer.networking.networkextension is packet-tunnel. You cannot deploy to a real device with that value. Even you download provisional certificate from Apple developer website with which you are signing and open it in text editor though it is a binary file, it clearly states the value as packet-tunnel-provider, how come then packet-tunnel works is a mystery to me. I lost 2 weeks for it.
As I mentioned I changed 'Action Sheet' extension to 'Network Extension', during the convert process I missed adding [Register] annotation on my PacketTunnelProvider class that I registered as the class supporting extension code. Probably NSDictionary nil error was related to it, not sure.
Now extension class is called, constructor and StartTunnel method is called and I can see logs in console app still not in 'Application Output', may be it will show logs for main app only.
CodePudding user response:
Question 1
We could enable the Network Extensions
option in Entitlements.plist
in graphical way , and check the string as source way , it should be packet-tunnel
not anything else .
Question 2
I test with your code , it works fine , I can't be able to reproduce the error , it seems no problem with your code .
Others
When testing on a real device , we should use the certificate and profile which enables Network Extensions
as well , we need to do that on Apple Developer , download the files and set them in project .