I am working on a Network Extension (Transparent Proxy) which is used by a DLP to prevent data leaks over the network. For each incoming NEAppProxyTCPFlow, the extension instantiates a custom wrapper object that creates an outbound nw_connection_t to the target host and port using Network framework.
When a client application connects to unreachable or blocked ports (e.g., 5222), our extension proxies this connection. As the destination is unreachable, the newly created connection transitions into nw_connection_state_waiting in Network Extension. Since macOS keeps nw_connection_t in the nw_connection_state_waiting state indefinitely, such connections cause system resource leaks. Over time, this leads to:
- exhaustion of system file descriptors and sockets.
- system-wide network unavailability until the extension process is killed.
Could you provide best-practice recommendations for handling nw_connection_state_waiting in a Network Extension to prevent such resource leaks?
I don’t think there’s a single best practice here. Rather, there are various approaches you can take and the best one is likely going to vary by the circumstances (something that’s pretty common problems when you’re ‘patching’ the system).
I see three basic options:
- Immediately fail the flow’s open request when the connection enters the
.waiting(_:)state. - Do that, but after some arbitrary timeout.
- Let the flow’s open request stall waiting for things to change.
I suspect that the first option is likely to be the best. If the client is itself using Network framework, this error is likely to cause it to move on to the next IP address and, if there are no more, enter its own .waiting(_:) state. However, things might work out less well for BSD Socket clients, which are likely to just fail immediately in response to such an error. OTOH, in the case of a bad port number, failing fast with ECONNREFUSED is what BSD Sockets clients are likely to expect.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"