11 Replies
      Latest reply on Mar 12, 2019 6:13 AM by roee84
      Ivan8585 Level 1 Level 1 (0 points)

        Hello,

         

        I'm trying to set DNS servers for my packet tunnel but it looks like OS ignores them. Here is how I set DNS servers:

         

        // configrations is a POJO with some tunnel information
        NEPacketTunnelNetworkSettings *settings = [[NEPacketTunnelNetworkSettings alloc] initWithTunnelRemoteAddress:configuration.remoteAddr];
        settings.IPv4Settings = [[NEIPv4Settings alloc] initWithAddresses:@[configuration.localAddr] subnetMasks:@[@"255.255.255.0"]];
        
        BOOL isFullTunnel = YES;
        if (configuration.routes.count > 0) {
            // create routes and add them
            settings.IPv4Settings.includedRoutes = routes;
            isFullTunnel = NO;
        } else {
            settings.IPv4Settings.includedRoutes = @[[NEIPv4Route defaultRoute]];
        }
        
        if (configuration.dnsServers.count > 0) {
            settings.DNSSettings = [[NEDNSSettings alloc] initWithServers:configuration.dnsServers];
        }
        
        [self setTunnelNetworkSettings:settings completionHandler:^(NSError * _Nullable error) {
            // some next actions
        }];
        
        

         

        When I start packet tunnel, it works fine and OS route networks packets right, but DNS requests go to defaul server (from network interface I guess), not to configured DNS servers.

         

        Here is how it looks like in tcpdump:

        375 105.231826 192.168.2.2 192.168.2.1 DNS 72 Standard query 0xf1d6 A web.test
        
        

         

        IP address 192.168.2.2 is my iOS device with started packet tunnel and 192.168.1.1 is IP address of device, I connected to by Wi-Fi (Wi-Fi hotspot) and "web.test" is hostname I want to get IP address for. Why OS ignores my DNS servers settings?

        • Re: DNS settings not work for tunnel
          angelovAlex Level 1 Level 1 (0 points)

          I met the same issue. Did you find a workaround for it? I think that we need to submit a bug report to Apple.

          • Re: DNS settings not work for tunnel
            angelovAlex Level 1 Level 1 (0 points)

            So it seems that it only works if [NEIPv4Route defaultRoute] is in includedRoutes. I haven't found better workaround then add  [NEIPv4Route defaultRoute] into included routes. And everything else, except your virtual network into exluded routes.

            My vpn uses 10.0.0.0/8, so that what I did:

              

            self.settings.IPv4Settings.includedRoutes = @[[NEIPv4Route defaultRoute]];
            self.settings.IPv4Settings.excludedRoutes = @[
                                                                   [[NEIPv4Route alloc] initWithDestinationAddress:@"0.0.0.0" subnetMask:@"248.0.0.0"],
                                                                   [[NEIPv4Route alloc] initWithDestinationAddress:@"8.0.0.0" subnetMask:@"255.0.0.0"],
                                                                   [[NEIPv4Route alloc] initWithDestinationAddress:@"9.0.0.0" subnetMask:@"255.0.0.0"],
                                                                   [[NEIPv4Route alloc] initWithDestinationAddress:@"11.0.0.0" subnetMask:@"255.0.0.0"],
                                                                   [[NEIPv4Route alloc] initWithDestinationAddress:@"12.0.0.0" subnetMask:@"252.0.0.0"],
                                                                   [[NEIPv4Route alloc] initWithDestinationAddress:@"16.0.0.0" subnetMask:@"240.0.0.0"],
                                                                   [[NEIPv4Route alloc] initWithDestinationAddress:@"32.0.0.0" subnetMask:@"240.0.0.0"],
                                                                   [[NEIPv4Route alloc] initWithDestinationAddress:@"48.0.0.0" subnetMask:@"240.0.0.0"],
                                                                   [[NEIPv4Route alloc] initWithDestinationAddress:@"64.0.0.0" subnetMask:@"192.0.0.0"],
                                                                   [[NEIPv4Route alloc] initWithDestinationAddress:@"128.0.0.0" subnetMask:@"128.0.0.0"],
                                                                   ];
            
              • Re: DNS settings not work for tunnel
                eskimo Apple Staff Apple Staff (10,875 points)

                I’ve been researching this as part of various DTS incidents.

                So it seems that it only works if [NEIPv4Route defaultRoute] is in includedRoutes.

                The above is correct as far as it goes.  In general iOS uses the DNS servers for the primary interface so, when your VPN claims the default route, it becomes the primary interface and thus its DNS servers are used.

                If you don’t want to become the default route (that is, you want to create a split tunnel rather than a full tunnel) you have two options:

                • You can configure specific match domains (via NEDNSSettings’s matchDomains property.  When you do this, iOS will use your tunnel’s DNS server for any server inside those domains.

                  For example, the VPN for Waffle Varnishing Inc might list waffle-varnishing.com, waffle-varnishing.some-cdn.com, waffle-varnishing.co.uk, and so on in its match domains.

                  [Oooh, waffle-varnishing.com isn’t registered, maybe I should register it!}

                • If you add an empty match domain (that is, set the property to an array containing an empty string), your DNS server is consulted before the primary interface’s DNS server.

                So, you normally set up a VPN in one of three ways:

                • full tunnel — The VPN is the primary interface and its DNS server is used by default.

                • split tunnel, match domains — The VPN is not the primary interface and the system consults its VPN server for just the specified match domains.

                • split tunnel, wildcard match domains — The VPN is not the primary interface and the system consults its DNS server for all domains first.

                Share and Enjoy

                Quinn “The Eskimo!”
                Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                let myEmail = "eskimo" + "1" + "@apple.com"

                  • Re: DNS settings not work for tunnel
                    Ivan8585 Level 1 Level 1 (0 points)

                    And as already checked, this

                     

                    • If you add an empty match domain (that is, set the property to an array containing an empty string), your DNS server is consulted before the primary interface’s DNS server.

                     

                    Doesn't work for some cases too.

                    • Re: DNS settings not work for tunnel
                      angelovAlex Level 1 Level 1 (0 points)

                      I can confirm that adding an empty match domain doesnt help.

                       

                          self.settings.IPv4Settings.includedRoutes = @[[[NEIPv4Route alloc] initWithDestinationAddress:@"10.0.0.0" subnetMask:@"255.0.0.0"]];
                          self.settings.IPv4Settings.excludedRoutes = @[[NEIPv4Route defaultRoute]];
                          self.settings.DNSSettings = [[NEDNSSettings alloc] initWithServers:@[@"10.9.0.2"]];
                          self.settings.DNSSettings.matchDomains = @[@""];
                      
                      • Re: DNS settings not work for tunnel
                        Hallk Level 1 Level 1 (0 points)

                        since ios 9.3

                         

                        split tunnel, wildcard match domains — The VPN is not the primary interface and the system consults its VPN server for all domains first.

                         

                        seems not to be true anymore if the entry exist in the public DNS is takes this one and doesn't start the VPN tunnel. If it doesn't exist it take the DNS from the VPN and connects to the VPN

                        • Re: DNS settings not work for tunnel
                          roee84 Level 1 Level 1 (0 points)

                          Hi eskimo, what if I want to use full tunnel

                          (full tunnel — The VPN is the primary interface and its DNS server is used by default), but I want to decide for each query, by the query's domain which DNS server to use (the VPN or the system). Is it doable? And can I do it via Packet tunnel provider, or only with NEDNSProxyProvider (which is problematic for me because it's limited only to supervised devices).

                      • Re: DNS settings not work for tunnel
                        Ivan8585 Level 1 Level 1 (0 points)

                        I created simple program for DNS test:

                         

                        - (IBAction)sendQuery:(id)sender
                        {
                            [self printDNSServers];
                        
                            CFHostRef host = CFHostCreateWithName(NULL, (CFStringRef)@"web.mobile");
                        
                            CFStreamError error;
                            if (!CFHostStartInfoResolution(host, kCFHostAddresses, &error))
                            {
                                NSLog(@"can't start resolution: %ld %d", error.domain, (int)error.error);
                                return;
                            }
                        
                            Boolean resolved;
                            CFArrayRef addresses = CFHostGetAddressing(host, &resolved);
                            if (addresses != NULL)
                            {
                                NSLog(@"resolved: %d", resolved);
                            }
                        }
                        
                        - (void)printDNSServers
                        {
                            res_state res = malloc(sizeof(struct __res_state));
                            int result = res_ninit(res);
                            if (result == 0)
                            {
                                NSLog(@"number of name servers: %d", res->nscount);
                                for (int i = 0; i < res->nscount; i++)
                                {
                                    NSLog(@"name server IP: %@", [NSString stringWithUTF8String: inet_ntoa(res->nsaddr_list[i].sin_addr)]);
                                }
                            }
                            free(res);
                        }
                        
                        
                        

                         

                        When I run app without my VPN app, I see following:

                         

                        DNSTestApp: number of name servers: 1

                        DNSTestApp: name server IP: 192.168.1.1

                        DNSTestApp: can't start resolution: 12 8

                         

                        So everything is correct. I connected to Wi-Fi spot with IP "192.168.1.1" to Internet and there is no such custom hostname "web.mobile" in public DSN servers. Now I start my VPN app and push button again:

                         

                        DNSTestApp: number of name servers: 1

                        DNSTestApp: name server IP: 100.1.1.3

                        DNSTestApp: can't start resolution: 12 8

                         

                        Test app shows correct IP address of my VPN DNS server "100.1.1.3" but for some reason still can't resolve custom hostname to IP address. Also I can't find any description about error with domain 12 and code 8.