4 ms·
There are Apple-supported ways to solve both these issues built in to the `NEPacketTunnelProvider` framework. No need to drop into obscure `ioctls`! The correc
by dcow 4y ago
There are Apple-supported ways to solve both these issues built in to the `NEPacketTunnelProvider` framework. No need to drop into obscure `ioctls`!
The correct way to solve the looping issue is by configuring the `excludedRoutes` property on the `NEIPv4|6Settings` object associated with your network extension. See: https://developer.apple.com/documentation/networkextension/neipv4settings/1406267-excludedroutes https://developer.apple.com/documentation/networkextension/n.... I imagine this is an important property for a dynamic mesh network to keep updated regularly as the topology changes.
The traffic egressing the wrong interface issue happens because the system handles swapping between WiFi and Cellular radios quite judiciously, and the BSD socket API isn't plugged into this management (AFAIK there's no way to get notified when the delegated interface changes, so you don't really know when to re-bind). Instead, you should use the provided `packetFlow` to write IP packets to the tunnel, which will always egress via the "correct" (whichever one the system decides is best at the moment) interface.
Tailscale's go library would need to implement hooks to call out to the platform implementation for Apple vs others, which is annoying. But, it's the right way and avoids these weird edge cases and bugs.
- ayewo 4y agoWould be interesting to hear the thoughts of Tailscale folks regarding your suggested fix.
- ayewo 4y agoIn addition to bradfitz returning to comment, I managed to get a response out of apenwarr on Twitter https://twitter.com/apenwarr/status/1647058229304651782 https://twitter.com/apenwarr/status/1647058229304651782
- pjmlp 4y agoIt is the usual issue that Linux folks keep looking at NeXTSTEP derivatives as yet another UNIX clone, instead of what is on top of it.
- dcow 4y agoAlso note there's an Android analog: https://developer.android.com/reference/android/net/VpnService#protect(int) https://developer.android.com/reference/android/net/VpnServi.... You call `protect` on sockets that should not send data through your tunnel. It's a bit more flexible and straightforward IMHO (:
- bradfitz 4y agoWe know about that. Very early versions of Tailscale tried to use it. It's not enough, though. A number of things in Apple's APIs are 90% of what we need.
- dcow 4y ago> Very early versions of Tailscale tried to use it, It’s not enough though. I know you’re not the author, but I think that type of background would have been an interesting/helpful addition to the blog post and have given it more grit/mileage. Personally I found the post to be link heavy and shallow. I read it wondering why you’re going through all this trouble, instead of understanding a clear problem and solution. A reader like I would be super interested in an explanation of the shortcomings of Apple’s framework and what product requirements or technical constraints make Tailscale’s bespoke approach necessary. I think it sets the stage better for a “we’re off the rails good thing Apple publishes the ifconfig sources, +1 for open source” type of message. > A number of things in Apple’s APIs are 90% of what we need. I know the feel.