NEFilterSocketFlow: How are we supposed to figure out the Listen state?

In the good old times of Kernel Extensions, when using a socket filter, it was possible to be informed that a socket entered the listen state.

Now, with the NEFilterDataProvider API there does not seem to be an obvious or intuitive way to be notified about this "event".

Questions:
  • Is a new flow supposed to be created for a listen "event"?

  • If this is the case, are we supposed to check that the flow is an incoming one with a nil remote endpoint?

It's not really possible to verify this theory as the documentation says about the remote endpoint property of a NEFilterSocketFlow:

This endpoint object may be nil when [NEFilterDataProvider handleNewFlow:] is invoked;

without mentioning in which cases the endpoint object would be nil.

Is a new flow supposed to be created for a listen "event"?

If by a listen event you mean something like accept() then yes that is generally what is happening here. For example, if you start a Content Filter for any TCP connections on 0.0.0.0 : 0 then when a new flow is initiated in either direction it should be handed off to handleNewFlow. When logging this out you can see:

Code Block text
Got a new (Outbound) flow
Got a new flow with local endpoint 0.0.0.0:0, remote endpoint x.x.x.x:443
Response to flow: ["remoteAddress": "x.x.x.x", "localPort": "0"]


Generated from:
Code Block swift
override func handleNewFlow(_ flow: NEFilterFlow) -> NEFilterNewFlowVerdict {
let direction = self.getDirection(direction: flow.direction)
os_log(.debug, log: self.log, "Got a new %{public}@ flow", direction)
guard let socketFlow = flow as? NEFilterSocketFlow,
let remoteEndpoint = socketFlow.remoteEndpoint as? NWHostEndpoint,
let localEndpoint = socketFlow.localEndpoint as? NWHostEndpoint else {
os_log(.debug, log: self.log, "Got a new flow defaulting to allow")
return .allow()
}
os_log(.debug, log: self.log, "Got a new flow with local endpoint %{public}@, remote endpoint %{public}@", localEndpoint, remoteEndpoint)
/* ... */
}
private func getDirection(direction: NETrafficDirection) -> String {
switch direction {
case .any:
return "(Any)"
case .inbound:
return "(Inbound)"
case .outbound:
return "(Outbound)"
default:
return "(No Recorded Direction)"
}
}


If this is the case, are we supposed to check that the flow is an incoming one with a nil remote endpoint?

You can. You can also look at the direction of the flow, like I illustrated above.


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
I mean the listen "event" that is provided by the
Code Block
.sf_listen

callback in the

Code Block
struct sflt_filter

KPI.



FB8177506
NEFilterSocketFlow: How are we supposed to figure out the Listen state?
 
 
Q