We're encountering an issue with our Network Extension (utilizing NEPacketTunnelProvider and NETransparentProxy) on macOS 14.5 (23F79).
On some systems, the VPN fails to automatically start after a reboot despite calling startVPNTunnel(). There are no error messages.
Our code attempts to start the tunnel:
.......
do {
try manager.connection.startVPNTunnel()
Logger.default("Started tunnel successfully")
} catch {
Logger.error("Failed to launch tunnel")
}
......
System log analysis reveals the tunnel stopping due to userLogout (NEProviderStopReason(rawValue: 12)) during reboot.
However, the Transparent Proxy stops due to userInitiated (NEProviderStopReason(rawValue: 1)) for the same reboot.
We need to understand:
Why the VPNTunnel isn't starting automatically.
Why the userLogout reason is triggered during reboot.
Additional Context:
We have manually started the VPN from System Settings before reboot.
Post
Replies
Boosts
Views
Activity
Hi team,
we have an application for macOS, and previously, all binaries and installers were signed using one Apple account.
However, we've transitioned to signing all binaries and installers with a different account.
Note: Our application is not available on the App Store; we distribute it at an enterprise level to our customers.
My question is: Can we expect app updates to function smoothly, or are there potential issues we should be aware of?
We have a PakcetTunnelProvider in SystemExtension with split tunnelling. We are setting up a private range of IP address (240.0.0.1/10) as include routes and a few match domains using NEPacketTunnelNetworkSettings. Everything works fine. We are able to setup tunnel settings and receive DNS as well as data traffic as per our rules.
However, when we execute the netstat -rn -f inet command in Terminal, it shows the following output:
240.0.0/10 link#8 UCS utun0
240.0.0.1 10.211.55.1 UGHS en0
240.0.0.2 10.211.55.1 UGHS en0
240.0.0.3 link#8 UHWIi utun0
After stopping the tunnel, some stale entries remain in the route table, as evidenced by the output of netstat -rn -f inet:
240.0.0/10 link#8 UCS utun0
240.0.0.3 link#8 UHWIi utun0
The expected behavior is that included routes should automatically clear once the tunnel stops.
** It's noteworthy that we've only observed this behaviour on Monterey OS; **
it works as expected on Ventura and Sonoma (where routes are automatically removed upon tunnel cessation)
We have tried to set the tunnel settings to nil explicitly, but no luck.
setTunnelNetworkSettings(nil) { _ in}
We're unsure why the routes aren't clearing properly on Monterey OS.
Thanks -
Happy questioning
We have a PacketTunnelProvider in a SystemExtension with split tunnelling. We specify several matching domains using NEPacketTunnelNetworkSettings, such as abc.example.com and xyz.example.com.
DNS requests of type A and AAAA for these domains are routed to the VPN interface, but we've noticed that SRV type requests do not reach the VPN interface. To test this, I'm creating an SRV type request from the terminal using the following command: dig SRV _https._tcp.example.com.
Please guide me if there are any specific configurations required for SRV records.
--Thanks
Happy Questioning and Enjoy
We have a PacketTunnelProvider in a SystemExtension with split tunneling. We are configuring a private IP address range of 240.0.0.1/10 as included routes and specifying a few matching domains using NEPacketTunnelNetworkSettings.
Once TunnelNetworkSettings has been applied successfully, a new utunx interface is created, and it includes routes for the 240.0.0.1/10 IP range. In our case, the interface name is utun3, where 'x' represents an integer value.
According to our business logic, we need to establish connections with some IPs from this range. To achieve this, we are utilizing the NWConnection class API to create connections with IP addresses
Like this
func establishConnection() {
// Specify the destination host and port
let host = "240.0.0.19"
let port = 80
// Create an NWHostEndpoint
let endpoint = NWHostEndpoint(hostname: host, port: "\(port)")
// Create an NWConnection
let connection = NWConnection(to: endpoint, using: .tcp)
connection.start(queue: .global())
}
For the above code, we have observed different behaviour for IP packets when creating connections from different targets.
In the first case, when we create a connection to the IP address 240.0.0.19 from the Main app target using the provided code, the IP packets correctly go through the utun3 interface because this address falls within the 240.0.0/10 range, which is part of the included routes.
However, in the second case, when we use the same code to create a connection to 240.0.0.19 from the Extension target, the IP packets go through the primary interface en0 rather than the utun3 interface.
**Question : **
Why do we have different behaviour for the same code?
How can we achieve the same behaviour as the Main app target in the System Extension target?
--
Thanks
We have implemented System Extension with the capability of Packet Tunnel Provider. Our Tunnel is full tunnel, so we are getting all packets for all traffic(DNS requests packets, app data packets).
There are some DNS requests, we are not interested to resolve them. so we want to upstream these request to physical interface to resolve them.
so how can we upstream DNS request from one interface to other interface?
We have implemented System Extension with the capability of Packet Tunnel Provider . Our Tunnel is full tunnel, so we are getting all packets for all traffic (DNS request packets and application data packets).
what we want to achieve
DNS request packets only for match domains should come to our Tunnel
All applications data packets for all apps should come to our Tunnel
Code that I have tried to achieve this
let networkSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: remoteAddress)
/* DNS settings. */
let dnsSettings = NEDNSSettings(servers: dnsServerList)
dnsSettings.matchDomains = ["example.com" ]
dnsSettings.matchDomainsNoSearch = true
networkSettings.dnsSettings = dnsSettings
/* IPv4 settings */;
let ipV4Settings = NEIPv4Settings(addresses: [tunnelAddress], subnetMasks: [tunnelSubnetMask])
ipV4Settings.includedRoutes = [NEIPv4Route.default()]
let localDNSServerRoute = NEIPv4Route(destinationAddress:localDNSServer, subnetMask: excludedRouteSubnetMask)
ipV4Settings.excludedRoutes = [localDNSServerRoute]
networkSettings.ipv4Settings = ipV4Settings
networkSettings.mtu = NSNumber(integerLiteral: mtuValue
We have set includedRoutes as NEIPv4Route.default() and in
excludedRoutes we have set localDNSServer address. But with this code we are getting all traffic (DNS and app data packets) even-though we have excluded the system/local DNS server.
Question
Can we achieve this functionality?
if yes, what mistake have we made in the code?
Thanks
I have IPv6 address string with an interface name. like fc00::1%utun3.
when I am trying to create URL object with this ip address string it is returning nil
let url = URL(string: "[fc00::1]%utun3")
print("Output -> \(url))
-----------
Output -> nil
is it any way that we can create an url with interface/utun name?
Thanks-:
I am creating a network connection with NWConnection class.
let serverURL = URL(string: "ws://example.com")!
let connection = NWConnection(to: .url(serverURL)) , using: parameters!)
connection?.start(queue: .main)
let suppose we have three interface a system.
en0
utun0
utun1
By default traffic for this connection will tunnel through en0
I wants that traffic for this connection should tunnel through utun1
how we can do this?
Thanks-:
We have implemented Network Extension with the capability of PacketTunnel. After setting the TunnelNetworkSettings it create a virtual interface. We have added additional link-local address to the virtual interface by including a IPv6 address in the addresses property of the NEIPv6Settings and all working as expected.
For Example -: Virtual interface is utun3 and link-local address is fe80::2
An entry has added in routing table like -> fe80::%utun3 fe80::2%utun3 UcI utun3 [output of netstat -rn]
now we are trying to create a Web-Socket connection with the link-local address
var connection: NWConnection?
var parameters: NWParameters?
let wsOptions = NWProtocolWebSocket.Options()
wsOptions.autoReplyPing = true
let tcpOptions = NWProtocolTCP.Options()
tcpOptions.enableKeepalive = true
parameters = NWParameters(tls: nil, tcp: tcpOptions)
parameters?.defaultProtocolStack.applicationProtocols.insert(wsOptions, at: 0)
connection = NWConnection(host: "fe80::1%utun3", port: ***, using: parameters!)
connection?.stateUpdateHandler = { [weak self] state in
print(" Link local received new state: \(state)")
}
connection?.start(queue: .main)
On Start connection has sent SYN and received SYN ACK
[Packets captured image]
at this point app is crashed this flowing error
`nw_endpoint_get_url called with null endpoint
2023-04-26 19:06:28.181408+0530 TunnelApp[3200:74170] [] nw_endpoint_get_url called with null endpoint, dumping backtrace:
[arm64] libnetcore-3013.80.5
0 Network 0x00000001b4e91c80 __nw_create_backtrace_string + 192
1 Network 0x00000001b4f38a70 nw_endpoint_get_url + 1216
2 Network 0x00000001b4e942c4 nw_ws_create_client_request + 100
3 Network 0x00000001b48fce58 __nw_ws_create_state_block_invoke + 428
4 Network 0x00000001b4a9f384 nw_protocol_options_access_handle + 108
5 Network 0x00000001b48f0a74 nw_ws_create_state + 248
6 Network 0x00000001b48f05c8 _nw_protocol_copy_ws_definition_block_invoke_2 + 192
7 Network 0x00000001b492ce5c nw_framer_protocol_connected + 368
8 libusrtcp.dylib 0x00000001bc0ca290 nw_protocol_tcp_wake_connected + 432
9 libusrtcp.dylib 0x00000001bc1011c0 tcp_input_available + 828
10 libusrtcp.dylib 0x00000001bc0cbd4c nw_protocol_tcp_input_available + 288
11 Network 0x00000001b539d4cc _ZL27nw_channel_add_input_framesP10nw_channelP11nw_protocol + 9188
12 Network 0x00000001b539aff8 _ZL30nw_channel_update_input_sourceP10nw_channelP11nw_protocolb + 328
13 Network 0x00000001b539a204 ___ZL17nw_channel_createP10nw_contextPhjPvjbbPb_block_invoke.29 + 72
14 libdispatch.dylib 0x00000001030029d4 _dispatch_client_callout + 20
15 libdispatch.dylib 0x00000001030062b4 _dispatch_continuation_pop + 816
16 libdispatch.dylib 0x00000001030215f0 _dispatch_source_invoke + 1732
17 libdispatch.dylib 0x000000010300e8c8 _dispatch_workloop_invoke + 2876
18 libdispatch.dylib 0x000000010301c990 _dispatch_workloop_worker_thread + 1064
19 libsystem_pthread.dylib 0x0000000102c0fd28 _pthread_wqthread + 288
20 libsystem_pthread.dylib 0x0000000102c17a7c start_wqthread + 8`
Any suggestions on it
Thanks
We have implemented Network Extension with the capability of PacketTunnel.
After setting the TunnelNetworkSettings it create a virtual interface. like utunX (X is a integer number)
Question/query
How can we add a custom link-local address for this virtual interface?
is it any NEPacketTunnelProvider or other APIs to do this?
Via terminal we can do this with ifconfig cmd -> Like ifconfig utunname inet6 add fe80::2
Thanks
We have implemented System Extension with the capability of Packet Tunnel Provide.
Snapshot of code is
let networkSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: remoteAddress)
/* DNS settings. */
let dnsSettings = NEDNSSettings(servers: dnsServerList)
dnsSettings.matchDomains = matchDomainList
networkSettings.dnsSettings = dnsSettings
/* IPv4 settings */
let ipV4Settings = NEIPv4Settings(addresses: [tunnelAddress], subnetMasks: [tunnelSubnetMask])
let includedRoute = NEIPv4Route(destinationAddress: includeRouteIP, subnetMask:includeRouteSubnetMask)
ipV4Settings.includedRoutes = [includedRoutes]
let excludedRoute = NEIPv4Route(destinationAddress:excludedRouteId, subnetMask: excludedRouteSubnetMask)
ipV4Settings.excludedRoutes = [excludedRoute]
networkSettings.ipv4Settings = ipV4Settings
/* Set maximum transmission unit size in bytes */
networkSettings.mtu = NSNumber(integerLiteral: mtuValue)
setTunnelNetworkSettings(networkSettings) { [weak self] error in
guard let self = self else { return }
//business logic
}
And all is working fine
After some time based on some business logic we get some IPs that we want to exclude.
Question/Query
is it any way that we can update/edit the previous ipV4Settings.excludedRoutes list without resetting TunnelNetworkSettings
or any other API that we can use to edit the Routing Table directly?
We have implemented System Extension with the capability of Packet Tunnel Provider.
Our Tunnel is full tunnel, so we are getting all packets for all traffic. We want to exclude some traffic from your tunnel based on URL.
NEIPv4Settings provides traffic exclusion based on ip addresses.
ipv4Settings?.excludedRoutes = [ NEIPv4Route(destinationAddress: "x.x.x.x", subnetMask: x.x.x.x")
is any way that we can do this exclusion based on URL?
Like:- ipv4Settings?.excludedRoutes = [ NEIPv4Route(destinationURL: URL(String: "example.com"))
Hi,
I am using WKWebView to showing some web content to user in my application.
it is working fine for valid url. but when I try to load a request for invalid url it's show an empty view and getting an error in didFailProvisionalNavigation delegate method.
but in other side SFSafariViewController shows an error message for invalid url. like "Safari cannot open the page because the server cannot found"
is it any configuration/api for WKWebView so we can achieve the same behaviour like SFSafariViewController for invalid url?
means, show the error message instead of blank screen.