Ok, I'll open a report. When I say I checked every combination I do mean every combination, even ones that didn't make sense. I would have expected the behavior you described. This is the log from enforceRoutes YES, includeAllNetworks NO, excludedRoutes set (pruned a bit because it was pretty verbose):
# Protocol properties seen by the extension:
#
[Jun 1, 2023 at 3:57:58 PM PDT] <Debug>: Protocol Properties:
. . .
includeAllNetworks = NO
excludeLocalNetworks = NO
excludeCellularServices = YES
excludeAPNs = YES
enforceRoutes = YES
. . .
# Network settings we're passing to setTunnelNetworkSettings:completionHandler:
#
[Jun 1, 2023 at 3:57:59 PM PDT] <Debug>: setting NEPacketTunnelNetworkSettings:
{
tunnelRemoteAddress = 10.200.1.200
DNSSettings = {
protocol = cleartext
server = (
172.16.1.1,
)
matchDomainsNoSearch = NO
}
proxySettings = {
autoProxyDiscovery = NO
autoProxyConfigurationEnabled = NO
HTTPEnabled = NO
HTTPSEnabled = NO
FTPEnabled = NO
SOCKSEnabled = NO
RTSPEnabled = NO
gopherEnabled = NO
excludeSimpleHostnames = NO
usePassiveFTP = YES
}
IPv4Settings = {
configMethod = manual
addresses = (
172.16.1.1,
)
subnetMasks = (
255.255.255.255,
)
includedRoutes = (
{
destinationAddress = 0.0.0.0
destinationSubnetMask = 0.0.0.0
},
)
excludedRoutes = (
{
destinationAddress = 10.10.0.0
destinationSubnetMask = 255.255.255.0
},
)
overridePrimary = NO
}
}
# And here we have the message printed when we receive a SYN packet for a destination. This
# should never be seen for excluded routes
#
[Jun 1, 2023 at 3:58:11 PM PDT] <Debug>: Trying to establish TCP tunnel to server 10.10.0.2:443...
Post
Replies
Boosts
Views
Activity
The definition of excludedRoutes:
excludedRoutes
The IPv4 network traffic that the system routes to the primary physical interface, not the TUN interface.
Makes it clear that they should not be sent to the TUN interface. This is not what's happening.
If we define neither includeAllNetworks nor enforceRoutes, then the excludedRoutes are properly excluded.
If we define either includeAllNetworks or enforceRoutes, then the excludedRoutes are ignored, and all traffic gets tunneled.
We tested every combination of the enforceRoutes, includeAllNetworks, excludeLocalNetworks, and overridePrimary options.
We can provide logs showing the network settings provided to the Network Extension framework at start time, along with the protocol settings, as well as the traffic from the excluded network going to the VPN extension.
I'll check this, but the excluded routes are not local networks. They're routes defined by the VPN gateway admin, who doesn't necessarily know anything about the user-side physical networks.
If it does work I'd be mightily surprised (and think that the documentation was even more obscure than I do now).
Kevin
Our particular issue was related to having a Host Application for testing.
We wanted to run unit tests on a system where, for reasons I won't go into here, we wanted to not run the application itself. We run tests by using the App scheme, which has the test targets listed under the Test option in the scheme editor.
If we set Host Application to none, then Xcode will try to run the unit tests. It will build them, and it will look like it's starting them, but will lock up and require a Force Quit.
The unit tests do run fine from the CLI in that case using xcodebuild.
If we select the AppUnitTest scheme and run the unit tests then it works, but you can't debug them. Setting breakpoints in the tests doesn't work.
Definitely an Xcode bug--Xcode should never need a Force Quit. If it's a testing scenario it can't handle, it shouldn't run it.
Ok, we figured out what was happening here.
enforceRoutes doesn't just ensure that traffic destined for the tunnel gets there, it also makes sure that traffic which does not match the tunnel does not go to the tunnel.
We set the DNS resolver as the IP of the VPN interface, but that's not always one of the includedRoutes for the VPN. In that case enforceRoutes ON will make DNS resolution not use the tunnel.
The workaround appears to be adding the IP address of the VPN interface to the includedRoutes. We haven't seen any side-effects from that yet.
This is a pretty weird behavior for enforceRoutes. Not the only unexpected problem we've seen with that flag -- We have another question open in the forums related to enforceRoutes as well, and its interaction with excludedRoutes:
https://developer.apple.com/forums/thread/730456
Cancel that. Still fails most of the time with the same symptoms & no information from Xcode...
My singleton definition was straight from Apple's docs, but it was definitely the cause of the problem.
I still have no $!!&%^$ idea what was going on, but changing it to
static let singleton : MyClass = {
let instance = MyClass()
return instance
}()
Caused things to start working.
Xcode was ridiculously opaque about what was failing, and why.
Looks like this is connected with having a Swift class that implements a singleton using
@objc class MyClass : NSObject {
static let singleton = MyClass()
@objc class func sharedInstance() -> MyClass {
return singleton
}
When I access the class in the test case using:
let myclass = MyClass.sharedInstance()
I get freezes, and when I don't things work fine.
There's no extra initialization being done in the initializer.
Works fine running the unit tests through the CLI, but using the Xcode GUI breaks horribly. No messages about problems, no crashes, but Xcode is dead in the water at that point :-(
Also, when this is happening there is no high CPU... It looks like basically nothing is happening.
When it locks up trying to quit it's the same thing. No churning CPU, just nothing happening.
Yes. Pre-iOS 16 we were just setting the IPv6 literal and it was working.
With iOS 16.0.3 customers saw that IPv6 was not working at all. It looks like that may have been partly an Apple issue, because there was other commentary about this on the net with other applications, and some of the problems went away with 16.1. This caused a lot of confusion about just whose bug it was :-)
With 16.1 we see that if we set an IPv6 literal without [] around it in the URL components host field then the resulting URL (components.url) has an empty host:
https:///<rest of request path>
When we set [] around the literal then we get a proper request:
https://[<IPv6 literal]/<rest of request path>
We do have it working at the moment on pre-iOS 16 & iOS 16.1+ by checking to see if the host in final URL is empty. We didn't want to do a check for OS version since we weren't sure exactly which one gave which behavior.
Encouraging hostname connections is fine, but sometimes literals are needed. Documentation to support that would be good.
Our problem isn't just orientation, and the failure message is consistent with every failure. The thing that seems oddest is that it will work fine the second call. In fact, if I break on the line of the call and make the same call in the debugger (and see it fail), then the call will succeed when I continue.
No, this was on a device running iOS 15. I haven't had any problems with iOS 16 so far.
Still haven't figured out what to set to see the ALF data, but I noticed that there are some messages from netext about the connection that's failing.
netext is a Microsoft Defender extension. If includeAllNetworks is on and Microsoft Defender is trying to do something with the traffic to the Gateway I suspect that it would be a problem.
Are there any known issues that you can say anything about WRT anti-malware (e.g., Microsoft Defender) & proxy software (e.g., iBoss) interacting with VPN packet tunnels?
It'll be tricky for me to find a test system which has none of these installed...
Thanks. I already added the logging profile, set the log config to debug, and turned up CFNETWORKS_DIAGNOSTICS. I'll take a look and see what I might have missed.
I occasionally see the "failed necp_set_socket_domain_attributes" even in success cases, so I suspect that one's a red herring.
Turns out there was some profile on their system that was blocking it. They didn't want to go into more detail on that.