I'm working on a Network Extension using NEDNSProxyProvider to inspect DNS traffic. However, I've run into a couple of issues:
DNS Proxy is not capturing traffic when a public DNS (like 8.8.8.8 or 1.1.1.1) is manually configured in the WiFi settings. It seems like the system bypasses the proxy in this case. Is this expected behavior? Is there a way to force DNS traffic through the proxy even if a public DNS is set?
Using DNS Proxy and DNS Settings simultaneously doesn't work. Is there a known limitation or a correct way to combine these?
How to set DNS or DNSSettings using DNSProxy?
import NetworkExtension
import SystemExtensions
import SwiftUI
protocol DNSProxyManagerDelegate {
func managerStateDidChange(_ manager: DNSProxyManager)
}
class DNSProxyManager: NSObject {
private let manager = NEDNSProxyManager.shared()
var delegate: DNSProxyManagerDelegate?
private(set) var isEnabled: Bool = false {
didSet {
delegate?.managerStateDidChange(self)
}
}
var completion: (() -> Void)?
override init() {
super.init()
self.load()
}
func toggle() {
isEnabled ? disable() : start()
}
private func start() {
let request = OSSystemExtensionRequest
.activationRequest(forExtensionWithIdentifier: Constants.extensionBundleID,
queue: DispatchQueue.main)
request.delegate = self
OSSystemExtensionManager.shared.submitRequest(request)
log.info("Submitted extension activation request")
}
private func enable() {
update {
self.manager.localizedDescription = "DNS Proxy"
let proto = NEDNSProxyProviderProtocol()
proto.providerBundleIdentifier = Constants.extensionBundleID
self.manager.providerProtocol = proto
self.manager.isEnabled = true
}
}
private func disable() {
update {
self.manager.isEnabled = false
}
}
private func remove() {
update {
self.manager.removeFromPreferences { _ in
self.isEnabled = self.manager.isEnabled
}
}
}
private func update(_ body: @escaping () -> Void) {
self.manager.loadFromPreferences { (error) in
if let error = error {
log.error("Failed to load DNS manager: \(error)")
return
}
self.manager.saveToPreferences { (error) in
if let error = error {
return
}
log.info("Saved DNS manager")
self.isEnabled = self.manager.isEnabled
}
}
}
private func load() {
manager.loadFromPreferences { error in
guard error == nil else { return }
self.isEnabled = self.manager.isEnabled
}
}
}
extension DNSProxyManager: OSSystemExtensionRequestDelegate {
func requestNeedsUserApproval(_ request: OSSystemExtensionRequest) {
log.info("Extension activation request needs user approval")
}
func request(_ request: OSSystemExtensionRequest, didFailWithError error: Error) {
log.error("Extension activation request failed: \(error)")
}
func request(_ request: OSSystemExtensionRequest, foundProperties properties: [OSSystemExtensionProperties]) {
log.info("Extension activation request found properties: \(properties)")
}
func request(_ request: OSSystemExtensionRequest, didFinishWithResult result: OSSystemExtensionRequest.Result) {
guard result == .completed else {
log.error("Unexpected result \(result.description) for system extension request")
return
}
log.info("Extension activation request did finish with result: \(result.description)")
enable()
}
func request(_ request: OSSystemExtensionRequest, actionForReplacingExtension existing: OSSystemExtensionProperties, withExtension ext: OSSystemExtensionProperties) -> OSSystemExtensionRequest.ReplacementAction {
log.info("Existing extension willt be replaced: \(existing.bundleIdentifier) -> \(ext.bundleIdentifier)")
return .replace
}
}
import NetworkExtension
class DNSProxyProvider: NEDNSProxyProvider {
var handlers: [String: FlowHandler] = [:]
var isReady = false
let queue = DispatchQueue(label: "DNSProxyProvider")
override func startProxy(options:[String: Any]? = nil, completionHandler: @escaping (Error?) -> Void) {
completionHandler(nil)
}
override func stopProxy(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
completionHandler()
}
override func handleNewUDPFlow(_ flow: NEAppProxyUDPFlow, initialRemoteEndpoint remoteEndpoint: NWEndpoint) -> Bool {
let id = shortUUID()
handlers[id] = FlowHandler(flow: flow, remoteEndpoint: remoteEndpoint, id: id, delegate: self)
return true
}
override func handleNewFlow(_ flow: NEAppProxyFlow) -> Bool {
return false
}
}
class FlowHandler {
let id: String
let flow: NEAppProxyUDPFlow
let remoteEndpoint: NWHostEndpoint
let delegate: FlowHandlerDelegate
private var connections: [String: RemoteConnection] = [:]
private var pendingPacketsByDomain: [String: [(packet: Data, endpoint: NWEndpoint, uniqueID: String, timestamp: Date)]] = [:]
private let packetQueue = DispatchQueue(label: "com.flowhandler.packetQueue")
init(flow: NEAppProxyUDPFlow, remoteEndpoint: NWEndpoint, id: String, delegate: FlowHandlerDelegate) {
log.info("Flow received for \(id) flow: \(String(describing: flow))")
self.flow = flow
self.remoteEndpoint = remoteEndpoint as! NWHostEndpoint
self.id = id
self.delegate = delegate
defer { start() }
}
deinit {
closeAll(nil)
}
func start() {
flow.open(withLocalEndpoint: flow.localEndpoint as? NWHostEndpoint) { error in
if let error = error {
self.delegate.flowClosed(self)
return
}
self.readFromFlow()
}
}
func readFromFlow() {
self.flow.readDatagrams { packets, endpoint, error in
if let error = error {
self.closeAll(error)
return
}
guard let packets = packets, let endpoints = endpoint, !packets.isEmpty, !endpoints.isEmpty else {
self.closeAll(nil)
return
}
self.processFlowPackets(packets, endpoints)
self.readFromFlow()
}
}
}
Any insights or suggestions would be greatly appreciated. Thanks!
Networking
RSS for tagExplore the networking protocols and technologies used by the device to connect to Wi-Fi networks, Bluetooth devices, and cellular data services.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I have added a Network Extension to my iOS project to use the WireGuard library. Everything was working fine up to Xcode 16, but after updating, I’m facing a build issue.
The build fails with the following error:
No such file or directory: '@rpath/WireGuardNetworkExtensioniOS.debug.dylib'
I haven’t explicitly added any .dylib to my project. The Network Extension target builds and runs fine on Xcode 16.
Description
Enterprise users are experiencing VPN resource access failures after upgrading to macOS Tahoe. Investigation indicates that configd (specifically IPMonitor) is incorrectly re-ranking network interfaces after a connectivity failure with probe server. This results in DNS queries routing through the physical network adapter (en0) instead of the VPN virtual adapter, even while the tunnel is active. This behaviour is not seen in previous macOS versions.
Steps to Reproduce:
Connect to an enterprise VPN (e.g., Ivanti Secure Access).
Trigger a transient network condition where the Apple probe server is unreachable. For example make the DNS server down for 30 sec.
Observe the system routing DNS queries for internal resources to the physical adapter.
Expected Results The: VPN virtual interface should maintain its primary rank for enterprise DNS queries regardless of the physical adapter's probe status.
Actual Results: IPMonitor detects an UplinkIssue, deprioritizes the VPN interface, and elevates the physical adapter to a higher priority rank.
Technical Root Cause & Logs:
The system logs show IPMonitor identifying an issue and modifying the interface priority at 16:03:54:
IPMonitor Detection: The process identifies an inability to reach the Apple probe server and marks en0 with an advisory:
Log snippet
2026-01-06 16:03:53.956399+0100 localhost configd[594]: [com.apple.SystemConfiguration:IPMonitor] configd[594] SetInterfaceAdvisory(en0) = UplinkIssue (2) reason='unable to reach probe server'
Interface Re-ranking: Immediately following, IPMonitor recalculates the rank, placing the physical service ID at a higher priority (lower numerical rank) than the VPN service ID (net.pulsesecure...):
Log snippet
2026-01-06 16:03:53.967935+0100 localhost configd[594]: [com.apple.SystemConfiguration:IPMonitor] 0. en0 serviceID=50CD9266-B097-4664-BFE6-7BAFCC5E9DC0 addr=192.168.0.128 rank=0x200000d
2026-01-06 16:03:53.967947+0100 localhost configd[594]: [com.apple.SystemConfiguration:IPMonitor] 1. en0 serviceID=net.pulsesecure.pulse.nc.main addr=192.168.0.128 rank=0x2ffffff
3.Physical adapter Is selected as Primary Interface:
2026-01-06 16:03:53.968145+0100 localhost configd[594]: [com.apple.SystemConfiguration:IPMonitor] 50CD9266-B097-4664-BFE6-7BAFCC5E9DC0 is the new primary IPv4
configd[594]: 50CD9266-B097-4664-BFE6-7BAFCC5E9DC0 is the new primary DNS
Packet Trace Evidence Wireshark confirms that DNS queries for enterprise-specific DNS servers are being originated from the physical IP (192.168.0.128) instead of the virtual adapter:
Time: 16:03:54.084
Source: 192.168.0.128 (Physical Adapter)
Destination: 172.29.155.115 (Internal VPN DNS Server)
Result: Connectivity Failure (Queries sent outside the tunnel)
Topic:
App & System Services
SubTopic:
Networking
Hi there,
We’re developing a companion app for a smart home product that communicates over the user’s local network.
To provision the device, it initially creates its own Wi-Fi network. The user joins this temporary network and enters their home Wi-Fi credentials via our app. The app then sends those credentials directly to the device, which stores them and connects to the local network for normal operation.
We’re using AccessorySetupKit to discover nearby devices (via SSID prefix) and NEHotspotManager to join the accessory’s Wi-Fi network once the user selects it. This workflow works well in general.
However, we’ve encountered a problem: if the user factory-resets the accessory, or needs to restart setup (for example, after entering the wrong Wi-Fi password), the device no longer appears in the accessory picker.
In iOS 18, we were able to work around this by calling removeAccessory() after the device is selected. This forces the picker to always display the accessory again. But in iOS 26, a new confirmation dialog now appears when calling removeAccessory(), which confuses users during setup.
We’re looking for a cleaner way to handle this scenario — ideally a way to make the accessory rediscoverable without prompting the user to confirm removal.
Thanks for your time and guidance.
For years our iOS apps have experienced a networking problem, which blocks them connecting to our servers via their API endpoint domains.
How can we recover after the scenario described below?
Using 3rd party error logging solutions, which have different endpoint domains, we can record the error:
NSUnderlyingError": Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, _kCFNetworkCFStreamSSLErrorOriginalValue=-9816, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9816, _NSURLErrorNWPathKey=satisfied (Path is satisfied), viable, interface: pdp_ip0[lte], ipv4, dns, expensive, uses cell}, "_NSURLErrorFailingURLSessionTaskErrorKey": LocalDataTask <DEDBFA4D-810D-4438-A6A0-95E3B9668B9E>.<308>, "_kCFStreamErrorDomainKey": 3, "_NSURLErrorRelatedURLSessionTaskErrorKey": <__NSSingleObjectArrayI 0x301f82e60>(
LocalDataTask <DEDBFA4D-810D-4438-A6A0-95E3B9668B9E>.<308>
)
"NSLocalizedDescription": An SSL error has occurred and a secure connection to the server cannot be made., "NSLocalizedRecoverySuggestion": Would you like to connect to the server anyway?
-9816 is the "server closed session with no notification" error based on comments in CoreFoundation source files. Subsequent API endpoint calls to the same domain return the same error.
The SSL error occurs most prevalently after a server outage. However, despite our best efforts, we have been unable to replicate triggering the problem for development purposes via experiments with our server.
When the error occurs the users report that:
Fully closing (i.e. not just sending to background) and reopening the app does NOT clear connectivity to our server being blocked.
Problem seems more prevalent when using mobile/cell data.
Switching from mobile/cell data to WIFI resolves the connection problem and then switching back to mobile/cell data shows the problem again. So the underlying problem is not cleared.
All other apps on the same device and mobile/cell data or WIFI connection, like Safari, have no problems connecting to the Internet.
Deleting and reinstalling, or updating (when an update is available) resolves the problem.
Or after waiting a few days the problem seems to resolve itself.
The last two point above suggest that something is persisted/cached in the app preventing it from connecting properly with subsequent network attempts.
Notes:
We have one shared instance of the URLSession in the app for its networking because we are aware of the perils of multiple URLSession instances.
We recently added conditions to call the URLSession await reset() method when detecting the SLL errors before repeating the request. It is debatable whether this reduces the problem as we still see logged cases with the subsequent requests hitting the same -9816 error.
URLSession configuration:
let config = URLSessionConfiguration.default
config.timeoutIntervalForResource = 22
config.timeoutIntervalForRequest = 20
config.requestCachePolicy = .reloadIgnoringLocalCacheData
config.urlCache = nil
We are developing a macOS VPN application using NEPacketTunnelProvider with a custom encryption protocol.
We are using standard On-Demand VPN rules with Wi-Fi SSID matching but we want to add some additional feature to the native behaviour.
We want to control the 'conenect/disconnect' button status and allow the user to interact with the tunnel even when the on demand rule conditions are satisfied, is there a native way to do it?
In case we need to implement our custom on-demand behaviour we need to access to this information:
connected interface type
ssid name
and being informed when it changes so to trigger our logic, how to do it from the app side?
we try to use CWWiFiClient along with ssidDidChangeForWiFiInterface monitoring, it returns just the interface name en0 and not the wifi ssid name.
Is location access mandatory to access wifi SSID on macOS even if we have a NEPacketTunnelProvider?
Please note that we bundle our Network Extension as an App Extension (not SystemExtension).
I am using a URLSessionWebSocketTask. When trying to receive messages while the app is backgrounded, the receive() method fails with an NSError where the domain is NSPOSIXErrorDomain and the code is ECONNABORTED. That behavior is good. However, when this happens, the URLSessionWebSocketTask reports a closeCode of invalid, which is supposed to denote that the connection is still open. However, the connection state property is reporting completed. I feel that the closeCode property should be reporting something like abnormalClosure in this case. Either way, this seems like a bug or the documentation is incorrect.
We are developing an iOS application that is interacting with HTTP APIs that requires us to put a unique UUID (a nonce) as an header on every request (obviously there's more than that, but that's irrilevant to the question here).
If the same nonce is sent on two subsequent requests the server returns a 412 error. We should avoid generating this kind of errors as, if repeated, they may be flagged as a malicious activity by the HTTP APIs.
We are using URLSession.shared.dataTaskPublisher(for: request) to call the HTTP APIs with request being generated with the unique nonce as an header.
On our field tests we are seeing a few cases of the same HTTP request (same nonce) being repeated a few seconds on after the other.
Our code has some retry logic only on 401 errors, but that involves a token refresh, and this is not what we are seeing from logs.
We were able to replicate this behaviour on our own device using Network Link Conditioner with very bad performance, with XCode's Network inspector attached we can be certain that two HTTP requests with identical headers are actually made automatically, the first request has an "End Reason" of "Retry", the second is "Success" with Status 412.
Our questions are:
can we disable this behaviour?
can we provide a new request for the retry (so that we can update headers)?
Thanks,
Francesco
I was excited to find out about Wi-Fi Aware in i[Pad]OS 26 and was eager to experiment with it. But after wiping and updating two devices (an iPhone 11 Pro and a 2018 11" iPad Pro) to Beta 1 I found out that neither of them support Wi-Fi Aware 🙁.
What current and past iPhone and iPad models support Wi-Fi Aware?
And is there a new UIRequiredDeviceCapabilities key for it, to indicate that an app requires a Wi-Fi Aware capable device?
I added a Content Filter to my app, and when running it in Xcode (Debug/Release), I get the expected permission prompt:
"Would like to filter network content (Allow / Don't Allow)".
However, when I install the app via TestFlight, this prompt doesn’t appear at all, and the feature doesn’t work.
Is there a special configuration required for TestFlight? Has anyone encountered this issue before?
Thanks!
Hello Apple Support Team,
We are experiencing a performance issue with HTTP/3 in our iOS application during testing.
Problem Description:
Network requests using HTTP/3 are significantly slower than expected. This issue occurs on both Wi-Fi and 4G networks, with both IPv4 and IPv6. The same setup worked correctly in an earlier experiment.
Key Observations:
The slowdown disappears when the device uses:
· A personal hotspot.
· Network Link Conditioner (with no limitations applied).
· Internet sharing from a MacBook via USB (where traffic was also inspected with Wireshark without issues).
The problem is specific to HTTP/3 and does not occur with HTTP/2.
The issue is reproducible on iOS 15, 18.7, and the latest iOS 26 beta.
HTTP/3 is confirmed to be active (via assumeHttp3Capable and Alt-Svc header).
Crucially, the same backend endpoint works with normal performance on Android devices and using curl with HTTP/3 support from the same network.
I've checked the CFNetwork logs in the Console but haven't found any suspicious errors or obvious clues that explain the slowdown.
We are using a standard URLSession with basic configuration.
Attempted to collect qlog diagnostics by setting the QUIC_LOG_DIRECTORY=~/ tmp environment variable, but the logs were not generated.
Question:
What could cause HTTP/3 performance to improve only when the device is connected through a hotspot, unrestricted Network Link Conditioner, or USB-tethered connection? The fact that Android and curl work correctly points to an issue specific to the iOS network stack. Are there known conditions or policies (e.g., related to network interface handling, QoS, or specific packet processing) that could lead to this behavior?
Additionally, why might the qlog environment variable fail to produce logs, and are there other ways to obtain detailed HTTP/3 diagnostic information from iOS?
Any guidance on further diagnostic steps or specific system logs to examine would be greatly appreciated.
Thank you for your assistance.
When setting up a packet tunnel with a profile that has includeAllNetworks set to true, we seemingly cannot send any traffic inside the tunnel using any kind of an API. We've tried using BSD sockets, as we ping a host only reachable within the tunnel to establish whether we have connectivity - this does not work. When using NWConnection from the Network framework and specifying the required interface via virtualInterface from the packet tunnel, the connection state never reaches ready. Our interim solution is to, as ridiculous as it sounds, include a whole userspace networking stack so we can produce valid TCP packets just to send into our own tunnel. We require a TCP connection within our own tunnel to do some configuration during tunnel setup. Is there no better solution?
Topic:
App & System Services
SubTopic:
Networking
Tags:
Network Extension
Network
System Configuration
Hi Team,
OS is prompting for local network permission for our application which runs as root level daemon.
As per the our analysis, it looks like it is prompting from our own library which is trying to get network info ' using /usr/sbin/system_profiler with "-xml -detailLevel basic SPNetworkDataType" and then trying to iterate to find DNS.ServerAddresses for each item. Then using [NSHost hostWithAddress:IPAddress];(When this library is not linked to the app then there is no prompt, so most likely this is the code that is resulting in the prompt).
Is this expected ? . Is there any other way that we can get DNS host name without being prompted for local network permission on mac OS 15
Greetings.I have an app today that uses multipeer connectivity extensively. Currently, when the user switches away from the app, MPC disconnects the session(s) - this is by design apparently (per other feedback). I'd like to hear if anyone has experimented with iOS9 multitasking / multipeer and whether MPC sessions can stay alive?Thanks
Topic:
App & System Services
SubTopic:
Networking
Tags:
Background Tasks
Multipeer Connectivity
Core Bluetooth
Hello eveybody,Currently I'm working on an app which connects to a device. During testing I encounter an internal error of NEHotspotConfigurationErrorDomain. See the log snippet:Domain=NEHotspotConfigurationErrorDomain Code=8 "internal error." UserInfo={NSLocalizedDescription=internal error.}This error appears randomly. In one day I encountered it three times. The only solution I can think of is catching this error somehow and then telling the user to restart the device.After this error appears, the wifi functionality of iOS in all third party apps seems to be broken. Only restarting helps as far as I know. Also there seems to be nothing we as app developers can do about it. Therefor I wonder if there is some way to prevent this error somehow? The only solution I can think of is catching this error somehow and then telling the user to restart the device.Also since there is not much information about this error on the web, it would be really nice if someone can clarify whats going on with this error.Regards.
Hi,
I’m implementing a macOS DNS Proxy as a system extension and running into a persistent activation error:
OSSystemExtensionErrorDomain error 9 (validationFailed)
with the message:
extension category returned error
This happens both on an MDM‑managed Mac and on a completely clean Mac (no MDM, fresh install).
Setup
macOS: 15.x (clean machine, no MDM)
Xcode: 16.x
Team ID: AAAAAAA111 (test)
Host app bundle ID: com.example.agent.NetShieldProxy
DNS Proxy system extension bundle ID: com.example.agent.NetShieldProxy.dnsProxy
The DNS Proxy is implemented as a NetworkExtension system extension, not an app extension.
Host app entitlements
From codesign -d --entitlements :- /Applications/NetShieldProxy.app:
xml
com.apple.application-identifier
AAAAAAA111.com.example.agent.NetShieldProxy
<key>com.apple.developer.system-extension.install</key>
<true/>
<key>com.apple.developer.team-identifier</key>
<string>AAAAAAA111</string>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.example.NetShieldmac</string>
</array>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
xml
com.apple.application-identifier
AAAAAAA111.com.example.agent.NetShieldProxy.dnsProxy
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>dns-proxy-systemextension</string>
</array>
<key>com.apple.developer.team-identifier</key>
<string>AAAAAAA111</string>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.example.NetShieldmac</string>
<string>group.example.NetShieldmac</string>
<string>group.example.agent.enterprise.macos</string>
<string>group.example.com.NetShieldmac</string>
</array>
DNS Proxy system extension Info.plist
On the clean Mac, from:
bash
plutil -p "/Applications/NetShieldProxy.app/Contents/Library/SystemExtensions/com.example.agent.NetShieldProxy.dnsProxy.systemextension/Contents/Info.plist"
I get:
json
{
"CFBundleExecutable" => "com.example.agent.NetShieldProxy.dnsProxy",
"CFBundleIdentifier" => "com.example.agent.NetShieldProxy.dnsProxy",
"CFBundleName" => "com.example.agent.NetShieldProxy.dnsProxy",
"CFBundlePackageType" => "SYSX",
"CFBundleShortVersionString" => "1.0.1.8",
"CFBundleSupportedPlatforms" => [ "MacOSX" ],
"CFBundleVersion" => "0.1.1",
"LSMinimumSystemVersion" => "13.5",
"NSExtension" => {
"NSExtensionPointIdentifier" => "com.apple.dns-proxy",
"NSExtensionPrincipalClass" => "com_example_agent_NetShieldProxy_dnsProxy.DNSProxyProvider"
},
"NSSystemExtensionUsageDescription" => "SYSTEM_EXTENSION_USAGE_DESCRIPTION"
}
The DNSProxyProvider class inherits from NEDNSProxyProvider and is built in the system extension target.
Activation code
In the host app, I use:
swift
import SystemExtensions
final class SystemExtensionActivator: NSObject, OSSystemExtensionRequestDelegate {
private let extensionIdentifier = "com.example.agent.NetShieldProxy.dnsProxy"
func activate(completion: @escaping (Bool) -> Void) {
let request = OSSystemExtensionRequest.activationRequest(
forExtensionWithIdentifier: extensionIdentifier,
queue: .main
)
request.delegate = self
OSSystemExtensionManager.shared.submitRequest(request)
}
func request(_ request: OSSystemExtensionRequest,
didFailWithError error: Error) {
let nsError = error as NSError
print("Activation failed:", nsError)
}
func request(_ request: OSSystemExtensionRequest,
didFinishWithResult result: OSSystemExtensionRequest.Result) {
print("Result:", result.rawValue)
}
}
Runtime behavior on a clean Mac (no MDM)
config.plist is created under /Library/Application Support/NetShield (via a root shell script).
A daemon runs, contacts our backend, and writes /Library/Application Support/NetShield/state.plist with a valid dnsToken and other fields.
The app NetShieldProxy.app is installed via a notarized, stapled Developer ID .pkg.
The extension bundle is present at:
/Applications/NetShieldProxy.app/Contents/Library/SystemExtensions/com.example.agent.NetShieldProxy.dnsProxy.systemextension.
When I press Activate DNS Proxy in the UI, I see in the unified log:
text
NetShieldProxy: [com.example.agent:SystemExtensionActivator] Requesting activation for system extension: com.example.agent.NetShieldProxy.dnsProxy
NetShieldProxy: [com.example.agent:SystemExtensionActivator] SystemExtensionActivator - activation failed: extension category returned error (domain=OSSystemExtensionErrorDomain code=9)
NetShieldProxy: [com.example.agent:SystemExtensionActivator] SystemExtensionActivator - OSSystemExtensionError code enum: 9
NetShieldProxy: [com.example.agent:SystemExtensionActivator] SystemExtensionActivator - validationFailed
And:
bash
systemextensionsctl list
-> 0 extension(s)
There is no prompt in Privacy & Security on this clean Mac.
Question
Given:
The extension is packaged as a system extension (CFBundlePackageType = SYSX) with NSExtensionPointIdentifier = "com.apple.dns-proxy".
Host and extension share the same Team ID and Developer ID Application cert.
Entitlements on the target machine match the provisioning profile and Apple’s docs for DNS Proxy system extensions (dns-proxy-systemextension).
This is happening on a clean Mac with no MDM profiles at all.
What are the likely reasons for OSSystemExtensionErrorDomain error 9 (validationFailed) with "extension category returned error" in this DNS Proxy system extension scenario?
Is there any additional configuration required for DNS Proxy system extensions (beyond entitlements and Info.plist) that could trigger this category-level validation failure?
Any guidance or examples of a working DNS Proxy system extension configuration (host entitlements + extension Info.plist + entitlements) would be greatly appreciated.
Thanks!
Recently, my application was having trouble sending udp messages after it was reinstalled. The cause of the problem was initially that I did not grant local network permissions when I reinstalled, I was aware of the problem, so udp worked fine after I granted permissions. However, the next time I repeat the previous operation, I also do not grant local network permissions, and then turn it back on in the Settings, and udp does not work properly (no messages can be sent, the system version and code have not changed).
Fortunately, udp worked after rebooting the phone, and more importantly, I was able to repeat the problem many times.
So I want to know if the process between when I re-uninstall the app and deny local network permissions, and when I turn it back on in Settings, is that permissions have been granted normally, and not fake, and not required a reboot to reset something for udp to take effect.
I'm not sure if it's the system, or if it's a similar situation as described here, hopefully that will help me find out
I have written the Transparent App Proxy and can capture the network flow and send it to my local server. I want to avoid any processing on the traffic outgoing from my server and establish a connection with a remote server, but instead of connecting to the remote server, it again gets captured and sent back to my local server.
I am not getting any clue on how to ignore these flows originating from my server.
Any pointers, API, or mechanisms that will help me?
Topic:
App & System Services
SubTopic:
Networking
Tags:
Network Extension
System Extensions
Endpoint Security
Hi all,
I have a working macOS (Intel) system extension app that currently uses only a Content Filter (NEFilterDataProvider). I need to capture/log HTTP and HTTPS traffic in plain text, and I understand NETransparentProxyProvider is the right extension type for that.
For HTTPS I will need TLS inspection / a MITM proxy — I’m new to that and unsure how complex it will be.
For DNS data (in plain text), can I use the same extension, or do I need a separate extension type such as NEPacketTunnelProvider, NEFilterPacketProvider, or NEDNSProxyProvider?
Current architecture:
Two Xcode targets: MainApp and a SystemExtension target.
The SystemExtension target contains multiple network extension types.
MainApp ↔ SystemExtension communicate via a bidirectional NSXPC connection.
I can already enable two extensions (Content Filter and TransparentProxy). With the NETransparentProxy, I still need to implement HTTPS capture.
Questions I’d appreciate help with:
Can NETransparentProxy capture the DNS fields I need (dns_hostname, dns_query_type, dns_response_code, dns_answer_number, etc.), or do I need an additional extension type to capture DNS in plain text?
If a separate extension is required, is it possible or problematic to include that extension type (Packet Tunnel / DNS Proxy / etc.) in the same SystemExtension Xcode target as the TransparentProxy?
Any recommended resources or guidance on TLS inspection / MITM proxy setup for capturing HTTPS logs?
There are multiple DNS transport types — am I correct that capturing DNS over UDP (port 53) is not necessarily sufficient? Which DNS types should I plan to handle?
I’ve read that TransparentProxy and other extension types (e.g., Packet Tunnel) cannot coexist in the same Xcode target. Is that true?
Best approach for delivering logs from multiple extensions to the main app (is it feasible)? Or what’s the best way to capture logs so an external/independent process (or C/C++ daemon) can consume them?
Required data to capture (not limited to):
All HTTP/HTTPS (request, body, URL, response, etc.)
DNS fields: dns_hostname, dns_query_type, dns_response_code, dns_answer_number, and other DNS data — all in plain text.
I’ve read various resources but remain unclear which extension(s) to use and whether multiple extension types can be combined in one Xcode target. Please ask if you need more details.
Thank you.
Topic:
App & System Services
SubTopic:
Networking
Tags:
Swift
Frameworks
Network Extension
System Extensions
I've had a Unreal Engine project that uses libwebsocket to make a websocket connection with SSL to a server. Recently I made a build using Unreal Engine 5.4.4 on MacOS Sequoia 15.5 and XCode 16.4 and for some reason the websocket connection now fails because it can't get the local issuer certificate. It fails to access the root certificate store on my device (Even though, running the project in the Unreal Editor works fine, it's only when making a packaged build with XCode that it breaks)
I am not sure why this is suddenly happening now. If I run it in the Unreal editor on my macOS it works fine and connects. But when I make a packaged build which uses XCode to build, it can't get the local issuer certificate. I tried different code signing options, such as sign to run locally or just using sign automatically with a valid team, but I'm not sure if code signing is the cause of this issue or not.
This app is only for development and not meant to be published, so that's why I had been using sign to run locally, and that used to work fine but not anymore.
Any guidance would be appreciated, also any information on what may have changed that now causes this certificate issue to happen.
I know Apple made changes and has made notarizing MacOS apps mandatory, but I'm not sure if that also means a non-notarized app will now no longer have access to the root certificate store of a device, in my research I haven't found anything about that specifically, but I'm wondering if any Apple engineers might know something about this that hasn't been put out publicly.