[Q] Has there been a change in macOS 15.3.2 and later that can explain why some UDP traffic is not seen by some Network Extensions when it is in previous macOS minor and major versions?
Incoming UDP Traffic in macOS 15.3 and later?
It’s hard to answer questions like that. I think you’re asking whether there’s a documented change, and the answer to that is “No.”
But I presume that you’re seeing a change, otherwise you wouldn’t have started this thread. Given that, it’d be helpful if you described what you’re actually seeing.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
It's actually more what is not seen.
TCP traffic is seen by the handleNewFlow method/function. UDP traffic is not.
Well, if you’ve already filed a bug then it’s generally a good idea to lead with that.
Are you able to reproduce this with the Filtering Network Traffic sample code?
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
I'm able to reproduce the problem with the SimpleFirewall example.
When following the procedure described in the ticket:
- UDP traffic is never seen.
- TCP traffic is seen.
As far as I can tell, the issue is with incoming UDP traffic.
I tried with a binary where the Apple signature was removed, I tried different ports.
I’d like to clarify your testing methodology here. By default, SimpleFirewall doesn’t filter UDP traffic. It sets up the filter like so:
// Filter incoming TCP connections on port 8888 let filterRules = ["0.0.0.0", "::"].map { address -> NEFilterRule in let localNetwork = NWHostEndpoint(hostname: address, port: FilterDataProvider.localPort) let inboundNetworkRule = NENetworkRule(remoteNetwork: nil, remotePrefix: 0, localNetwork: localNetwork, localPrefix: 0, protocol: .TCP, direction: .inbound) return NEFilterRule(networkRule: inboundNetworkRule, action: .filterData) }
which means it only sees TCP. Presumably your modified this to include UDP as well. Is that right?
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
I removed the filter.
- Outbound UDP flows are all seen.
- The inbound UDP flow in the test scenario is never seen.
- Some other inbound UDP flows are seen.
Here's the modified source I used for the FilterDataProvider:
// MARK: Properties // The TCP port which the filter is interested in. // MARK: NEFilterDataProvider override func startFilter(completionHandler: @escaping (Error?) -> Void) { completionHandler(nil) } override func stopFilter(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { completionHandler() } override func handleNewFlow(_ flow: NEFilterFlow) -> NEFilterNewFlowVerdict { guard let socketFlow = flow as? NEFilterSocketFlow, let remoteEndpoint = socketFlow.remoteEndpoint as? NWHostEndpoint else { os_log("Early return") return .allow() } os_log("Got a new flow (socket protocol: %d direction: %d) with remote endpoint %{public}@", socketFlow.socketProtocol, socketFlow.direction.rawValue, remoteEndpoint) os_log("Got a new flow with remote port %{public}@", remoteEndpoint.port) return .allow() } }