Is it possible to split tunnel using system extensions based NE Transparent Proxy in Catalina?

Let's say Mac has two Internet connections. One is LAN, the other is Wifi. LAN is primaryInterface. In NE Transparent Proxy provider, I want to split tunnel based on App/Process or destination IP address. For example, in [MyNEAppProxyProvider(subclass of NEAppProxyProvider) handleNewFlow:flow], if the destination IP is IP1, I want this traffc to go through Wifi. So I call BSD bind() to Wifi address, connect() to IP1, then transfer data between flow and the new connection(via Wifi). Is it possbile to do it in this way? Any help would be appreciated.

Accepted Reply

I have a couple of things you might try:

  • Rather than binding to the interface’s source address, trying binding to the interface directly, that is, using

    IP_BOUND_IF
    .
  • You wrote:

I set IP1 to

NETransparentProxyNetworkSettings.includedNetworkRules

Just for the sake of experiment, try catching this connection via other means. For example, use a rule that matches a wildcard address and the destination port. Does the

bind
/
connect
work then?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

So I call BSD

bind
to Wifi address,
connect
to IP1, then transfer data between flow and the new connection (via Wifi). Is it possbile to do it in this way?

I can’t see why not. Apple’s networking stack supports scoped routing, so if a connection is bound to a specific interface then its traffic will run over that interface. Did you try this? What happened?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Yes. I did try it. But connect() API call failed.


I set IP1 to NETransparentProxyNetworkSettings.includedNetworkRules, then set network setting using [MYNEAppProxyProvider setTunnelNetworkSettings] method, so in [MyNEAppProxyProvider handleNewFlow:flow] I can get the flow connecting to IP1. The bind() to Wifi address success, however, connect() to IP1 failure immedaitely with error 49 which is EADDRNOTAVAIL (Can't assign requested address). I tried call [flow openWithLocalEndpoint:IP1Address completionHandler:^(){NSError *error}] before establishing new connection via Wifi, [flow openWithLocalEndpoint] is success, but connect() failed with same error. If I didn't call bind() before connect(), then the connection will go through LAN instead of Wifi I think because LAN is primaryInterface.

I have a couple of things you might try:

  • Rather than binding to the interface’s source address, trying binding to the interface directly, that is, using

    IP_BOUND_IF
    .
  • You wrote:

I set IP1 to

NETransparentProxyNetworkSettings.includedNetworkRules

Just for the sake of experiment, try catching this connection via other means. For example, use a rule that matches a wildcard address and the destination port. Does the

bind
/
connect
work then?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

IP_BOUND_IF works! Thank you so much!