Hello,
Recently I am trying to add stub dns server to my Network Extension (a VPN app), after some research on this forum, and since my language is C, I have the following plan:
- create a udp socket which use setsockopt(IP_BOUND_IF) to bound the socket to the utun if index obtained, and also bind to the address of the utun address I set(let's say 192.168.99.2), then listen on the udp port 53 which is ready to handle dns request.
- configure the dns server to 192.168.99.2 in the provider's Network Settings, thus iOS system will send udp query to the udp socket created in step 1, and it can then do some split dns function such as resolve using local interface (cellular or wifi), or some nameserve which will be routed to the VPN tunnel (will create new UDP socket and do IP_BOUND_IF to ensure the traffic will enter the VPN tunnel), and the result should be return to the system and then the non VPP apps.
But I observer weird issue, indeed I can get the system send the dns request to the listening udp socket and I can get the result write to the system(address like 192.168.99.2:56144, the port should be allocated by the iOS system's DNS component) without any failure(I did get some error before due to I using the wrong utun if index, but fixed it later), but it seems non VPN app like browser can't get the resolved ip for domains.
I want to ask is this limited by the sandbox? or any special sock opt I need to do.
Thanks.
PS:
- in the provider's network settings, all the system's traffic will be point to the utun, which means the VPN process will process all the traffic.
- the reason I do not set the dns server to utun peers side which is my userspace networking stack's ip (192.168.99.1) is the stack is not be able to leverage some dns libraries due to architecture issue. (it's fd.io vpp which we ported to apple platform).
I just wanna make it clear that UTUN interfaces are an implementation detail of the packet tunnel provider mechanism on iOS, and on macOS for that matter. While it’s fine to assume that your packet tunnel provider has a network interface, you shouldn’t assume that it’s a UTUN interface, or assume any other interface-specific details about it.
The canonical way to get your tunnel’s interface is via the virtualInterface
property. That returns an NWInterface
, and you can get BSD-specific stuff, like the BSD interface name, from its properties [1].
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] If you’re using a C-based language this is an nw_interface_t
and the routines are nw_interface_get_name
/ nw_interface_get_index
.