NEFilterDataProvider - how to get socket's interface

I'm implementing NEFIlterDataProvider where I would like to drop sockets that will be bound to specific interface, but I can't find interface parameter anywhere. Is that even possible to do? I tried to do the same thing with NEFilterPacketProvider, which provides interface information in packetHandler callback, but callback always provides physical interface (en0) even though I'm connected to VPN and should provide virtual interface. Can you give me a hint how could I drop packets or sockets bound to specific network interface?

Accepted Reply

but localEndpoint of a NEFilterSocketFlow usually has 0.0.0.0 hostname so I can not match it with any interface. Is there a way to get actual IP address of a localEndpoint?

Usually the localEndpoint will stay either the default address or nil until the actual connection is made. When handleNewFlow provides:

[NEFilterNewFlowVerdict filterDataVerdictWithFilterInbound:YES peekInboundBytes:PEEKSIZE filterOutbound:YES peekOutboundBytes:PEEKSIZE];

and the flow starts receiving/sending data from handleInboundDataFromFlow and handleOutboundDataFromFlow do you still see the localEndpoint being the default address or nil?

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

Replies

I'm implementing NEFIlterDataProvider where I would like to drop sockets that will be bound to specific interface, but I can't find interface parameter anywhere. Is that even possible to do?

This is a good question as there is no readily apparent way to extract nw_interface_t from APIs like NEFilterSocketFlow or NEFilterFlow. One thing you could try here is to examine the localEndpoint of a NEFilterSocketFlow and then use a low level API like getifaddrs to examine if the local endpoint address matches anything interface on the machine with the same address. This seems like a lot more work than it should be though and probably best to open an Enhancement Request for this. Please follow up with the Feedback ID.

If you do end up going the getifaddrs route, keep in mind that the localEndpoint may not be available until methods like handleOutboundDataFromFlow are hit. There are several cases where handleNewFlow does not have the localEndpoint value set because the socket is not established yet.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

Thanks for the suggestion. I managed to retrieve all interfaces on the machine with their addresses using getifaddrs, but localEndpoint of a NEFilterSocketFlow usually has 0.0.0.0 hostname so I can not match it with any interface. Is there a way to get actual IP address of a localEndpoint?

but localEndpoint of a NEFilterSocketFlow usually has 0.0.0.0 hostname so I can not match it with any interface. Is there a way to get actual IP address of a localEndpoint?

Usually the localEndpoint will stay either the default address or nil until the actual connection is made. When handleNewFlow provides:

[NEFilterNewFlowVerdict filterDataVerdictWithFilterInbound:YES peekInboundBytes:PEEKSIZE filterOutbound:YES peekOutboundBytes:PEEKSIZE];

and the flow starts receiving/sending data from handleInboundDataFromFlow and handleOutboundDataFromFlow do you still see the localEndpoint being the default address or nil?

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

I wanted to elaborate on Matt’s comment:

Usually the localEndpoint will stay either the default address or nil until the actual connection is made.

To be clear, this isn’t a bug. Due to the way the our systems connect [1] we don’t know which local address will be used for a connection until it’s actually connected.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] If you’re curious, read up on Happy Eyeballs.

Yes, in handleInboundDataFromFlow and handleOutboundDataFromFlow I can see actual address. Thank you

  • Great news!

Add a Comment