VPN Split tunnel

Hi,


I would like to only route DNS request through the vpn tunnel. I can successfully do this when connected on wifi (IPv4) by using the following NEPacketTunnelNetworkSettings:


let dnsSettings = NEDNSSettings(servers: ["208.67.222.123", "208.67.220.123"])

// This overrides system DNS settings

dnsSettings.matchDomains = [""]

networkSettings.dnsSettings = dnsSettings

networkSettings.ipv4Settings?.excludedRoutes = [NEIPv4Route.default()]

networkSettings.ipv4Settings?.includedRoutes = [

NEIPv4Route(destinationAddress: "208.67.222.123", subnetMask: "255.255.255.0"),

NEIPv4Route(destinationAddress: "208.67.220.123", subnetMask: "255.255.255.0")

]


As I understand this basically sets up a split tunnel where only dns traffic is sent to the tunnel, everything else is excluded. I can also see the vpn server is essentially only handling dns queries. I am using openVPN client code integrated into the app connecting to SoftEther VPN.

The problem occurs when the iOS device is connected only with cellular carrier data which is an IPv6 network. Any advice on how to configure the settings to have the same behaviour in IPv6.

When I set the tunnel up with full tunnel on cellular, I can see all traffic routed to the VPN server. It also looks like a DNS request are routed to the VPN server and handled as IPv4 dns request.

Alternatively is there a way to force tunnel to only use ip4 dns.

Any help in me understanding this will be very helpful. Thank you.

I would like to only route DNS request through the vpn tunnel.

To start, this high-level goal is not easy to achieve using a packet tunnel provider. Packet tunnel providers were designed to implement actual VPN, not for capturing DNS traffic. If you want to capture DNS traffic then the correct option is to use a DNS proxy provider.

IMPORTANT Alas this doesn’t work for most people because DNS proxy providers can only be deployed to supervised devices )-: If you’d like to use a DNS proxy provider and are stymied by this restriction, I encourage you to file a bug requesting that it be lifted. It would help if you described your user-level requirements and any ‘heroic’ workaround efforts you’ve applied.

As I understand this basically sets up a split tunnel where only dns traffic is sent to the tunnel, everything else is excluded.

Kinda. In the packet tunnel provider world a split tunnel is based on IP routing, not on the protocol, so it’s not possible to create a DNS-only split tunnel. With things set up like this then, if the device tries to talk to a non-DNS service that happens to be on the same network as your DNS server, it’s going to go through the tunnel.

The problem occurs when the iOS device is connected only with cellular carrier data which is an IPv6 network.

This is not your only problem. Right now you’re hard coding a bunch of DNS server IP addresses and that will only work on specific networks. The problem you’re seeing on WWAN is a symptom of a bigger problem, namely that different networks use different DNS servers and there’s no way to set up routing so that it adapts to the system’s DNS configuration.

You could try to probe the system’s DNS configuration and adjust your routing based on that, but this is unlikely to work well. To start, iOS does not have a good way to get at the system’s DNS configuration [1]. This isn’t surprising given that the correct way to do this is with a DNS proxy provider.

Share and Enjoy

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

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

[1] There two options in this space:

  • NEDNSProxyProvider
    has the
    systemDNSSettings
    property, but that only helps if you’re a DNS proxy provider.
  • You can get some information via legacy bind APIs.

Neither works particularly well. Specifically, neither lets you view all the details of the system’s DNS settings (per-interface DNS, match domains, and so on) and that limits your ability to accurately track system DNS behaviour.

VPN Split tunnel
 
 
Q