NetworkExtension "leaks" NEFilterSocketFlow for UDP flows?

Hi all,

I run into a memory issue in NetworkExtension. I hope my NetworkExtension will filter all traffics (any hosts/ports, any protocol, any direction).

After running for 5 days, the NetworkExtension.framework keeps 20,000+ instances of NEFilterSocketFlow.

I don't believe a laptop will run 20,000 network connections at the same time, it seems like an issue from system frameworks.

I run the test on macOS 11.0.1 (20B29), it can also reproduced on macOS 11.1 (20C5048k).

I use the following snippet to reproduce the issue. To use this code, get a copy of "Filtering Network Traffic" sample code and replace the file.


FB8924681

Shay
Interesting. Thanks for opening a bug report on this. I copied myself on it for further updates. Out of curiosity, do you see the same thing if you target the NENetworkRule to use the remoteNetwork with an NWHostEndpoint on TCP connections instead of the localNetwork for UDP?


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Hi Eaton

It seems that filtering TCP traffic won't leak NEFilterSocketFlow. If I close network applications a few moments before taking memgraph, there will be almost no NEFilterSocketFlow left (instead of 10~15 more NEFilterSocketFlow per minute if UDP traffic is also filtered).

Shay

It seems that filtering TCP traffic won't leak NEFilterSocketFlow.

Yeah, that's what I had suspected. Thank you for confirming. Please add this to your bug report.

Now, I realize since you are noticing this while targeting the localNetwork, and because this is UDP, this /may/ not be a valid test, but it would be worth trying to see if the same behavior is observed on the remote side as well. Just as a data point for your bug report.

Code Block swift
let anyHostAndPortRule = NENetworkRule(
remoteNetwork: NWHostEndpoint(hostname: "0.0.0.0", port: "0"),
remotePrefix: 0,
localNetwork: nil,
localPrefix: 0,
protocol: .UDP,
direction: .any
)
let filterRule = NEFilterRule(networkRule: anyHostAndPortRule, action: .filterData)
let filterSettings = NEFilterSettings(rules: [filterRule], defaultAction: .allow)


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Hi all,

I did some experiment on user's computer, it seems that the leak might relate to netbios (UDP targeting local port 137, 138) and mDNSResponder (UDP targeting local port 5353).

Run 1: I forgot to backup the code for filtering all UDP traffic, the app retained 786 NEFilterSocketFlow instances in 30 minutes.

Run 2: When filtering everything except the traffic mentioned above, the app retained only 5 NEFilterSocketFlow in 20 minutes.

Code Block swift
let rules = ["0.0.0.0", "::"].map { address -> [NEFilterRule] in
["137", "138", "5353"].map { port -> NEFilterRule in
let localNetwork = NWHostEndpoint(hostname: address, port: port)
let networkRule = NENetworkRule(
remoteNetwork: nil,
remotePrefix: 0,
localNetwork: localNetwork,
localPrefix: 0,
protocol: .UDP,
direction: .any
)
return NEFilterRule(networkRule: networkRule, action: .allow)
}
}.flatMap { $0 }
let filterSettings = NEFilterSettings(rules: rules, defaultAction: .filterData)


It would be more precise if I do another experiment filtering everything (to compare with run 2), but I think the data above should be sufficient to isolate the problem, and that's the workaround that I've found with current NetworkExtension APIs.

Shay
NetworkExtension "leaks" NEFilterSocketFlow for UDP flows?
 
 
Q