No, the tunnel is not failing. As I said when I started this thread:
The above chunk of C code is used to open TCP sockets on public and private servers on many platforms including Android and Mac OS. On iOS, it works if the device, an XR running 14.4.2, has an internal IP address when connecting to a public server. However, if the XR has a public IP address as it does when not connected to wifi, it fails with this in the log calling the same public server (or any public server) and errno = 1, Operation not permitted.
When the extension is started, the vpn becomes ready, and the above chunk of code sets up encryption with a server by first making a tcp connection to it and sending an encrypted packet through that connection that identifies the client and then sets up OpenSSL. Then control information and output from the vpn goes through that interface.
The problem is when the device is running iOS 14+ and has a public ip address, meaning either wifi is disabled or it's not connected to wifi, the connect() for the tcp connection fails with:
Code Block Sandbox: <extension name>(<process #>) deny(1) network-outbound*:<port no> |
The deny(1) means errno == 1.
I know that this is not a problem with extensions on iOS 12.5.2, and I also made sure that connect() worked from the app. So the situation is that a basic connect() fails in network extensions on iOS 14+, but works outside of extensions on 14+ and works inside and outside of extensions on 12.5.2 (and I'll assume earlier versions).
I see no other reason for connect() to fail in this single situation unless it is a bug/regression or a lack of documentation that says that BSD sockets are no longer supported in network extensions running iOS 14+ on devices with public ip addresses, which makes C next to useless. Saying that NWConnection is "better equipped" doesn't explain why the industry standard connect() fails after working on earlier releases. And without an OpenSSL implementation for it, it is only "better equipped" for relatively simple stuff.
It would be acceptable if I could get a socket descriptor out of a NWConnection, but that is not possible. Since connect() works in the app, I might be able to make it work if the app can do background processing, but this is not an acceptable use of background processing from what I can tell.