A few days ago I wrote Little Snitch "denied" connections leak your IP address in which I explained that connections denied by Little Snitch are still leaking your IP address, a major privacy issue. The addendum of the blog post notes that I had briefly tested LuLu and saw some of the same behavior. After I published my blog post, I sent a link to Patrick Wardle, the developer of LuLu, who has been very responsive and helpful. Moreover, LuLu is open source, so I was able to examine how it works exactly. On further testing with LuLu, I came to believe that there's actually a bug in the macOS network filter extension implementation. I've now filed FB12088655 with Apple: Privacy: Network filter extension TCP connection and IP address leak.
The bug report includes a sample network filter extension Xcode project, which I'm providing for download here. The extension filters all connections to ports 80 (http) and 443 (https), and it always returns [NEFilterNewFlowVerdict dropVerdict]
from [NEFilterDataProvider handleNewFlow:]
. In other words, it blocks all http and https connections. To test yourself, you'll need to replace my development team with your own development team in the Xcode project, build and run the app, then enable the extension in System Preferences/Settings and allow it to filter content when the system dialog pops up. Then you'll want to run tcpdump
in Terminal to capture the packets:
You can also search for "FOOBAR" in the Console app for some connection logging from my extension.
I don't think the bug occurs with every connection. It seems somewhat random and may be a race condition in Apple's code. What you'll sometimes see in the packet trace is the first 2 steps of the TCP 3-step handshake: the SYN packet from your Mac to the remote server, and the SYN-ACK packet from the remote server to your Mac. No further packets are sent from your Mac, and the remote server may do a TCP retransmission of the SYN-ACK packet when it doesn't get an ACK from your Mac.
I believe that this macOS bug accounts for everything strange I saw with LuLu, which has a relatively simple implementation of connection blocking. It's difficult for me to determine how much this bug accounts for the behavior of Little Snitch, because I don't have its source code, and the developers of Little Snitch stated that they're doing deep packet inspection, which I would assume uses the API [NEFilterNewFlowVerdict filterDataVerdictWithFilterInbound: peekInboundBytes: filterOutbound: peekOutboundBytes:]
. As I said in my previous blog post, with regard to Little Snitch, "The information leak appears to occur for every TCP connection, as far as I can tell", which is more than I'm seeing with LuLu or my sample project.