Obtaining IP and port number of local services with iOS 14.5

Hello,

We provide a cross-platform network communication library to our customers, implementing secure application level tunnelling (and more) for use primarily in IoT scenarios. The library is implemented in C++. For discovering local devices, we have used a custom mDNS implementation based on raw BSD sockets - with the iOS 14.5 restrictions this is apparently no longer possible and we are looking for alternative options.

However, we cannot find a non-deprecated way to obtain the local UDP IP address and port number of discovered services. The NSNetService API is deprecated and the NWBrowser API only gives you the service names for use with NWConnection (the latter is not applicable due to the cross-platform implementation of our proprietary protocol).

Are there any (clean) way to obtain a local service's IP address and port number for use with lower level implementations like ours? Or do we have to resort to a hack where we stuff the normal A and AAAA record contents + port number into TXT records that apparently are ok to retrieve with NWBrowser?

Thanks for clarifying!

Ulrik, Nabto

For discovering local devices, we have used a custom mDNS implementation based on raw BSD sockets - with the iOS 14.5 restrictions this is apparently no longer possible

That’s not true. The only change in this space in iOS 14.5 is that we now enforce local network privacy for BSD Sockets clients. If you follow the local network privacy rules (see the Local Network Privacy FAQ) your existing code should continue to work just fine.

Having said that, we strongly discourage folks from using their own DNS resolver (mDNS, but also uDNS) on our platforms. The built-in resolver does stuff that’s simply not possible to replicate in third-party code.

However, we cannot find a non-deprecated way to obtain the local UDP IP address and port number of discovered services.

Before I go further I want to be clear that you should not be resolving to an IP address, because there’s no guarantee that DNS resolution will yield a single IP address. We recommend, instead, that you resolve to a DNS name and port, and then pass the DNS name to a system API that implements connect by name (like NWConnection).

If you insist on working with IP addresses then you take on the burden of implementing Happy Eyeballs, which is not fun (especially with UDP).

Coming back to your question about resolving a service, this is a known hole in the Network framework story right now (r. 73266838). There are two ways to get around this:

  • Continue to use NSNetService — While this is deprecated, it’s unlikely to be going away any time soon (and I’m hopeful we’ll ship a fix for 73266838 long before that happens).

    See this post for an example of how to do this.

  • Drop down to <dns_sd.h> — This API is a lot less nice than our higher-level APIs but, given that you’re currently working with BSD Sockets in C++, I doubt that’ll phase you (-:

    See the DNSSDObjects sample code for an example of how to use this.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

For discovering local devices, we have used a custom mDNS implementation based on raw BSD sockets - with the iOS 14.5 restrictions this is apparently no longer possible

That’s not true. The only change in this space in iOS 14.5 is that we now enforce local network privacy for BSD Sockets clients. If you follow the local network privacy rules (see the Local Network Privacy FAQ) your existing code should continue to work just fine.

I assume you mean it works fine if the multicast entitlement is applied? The problem is we provide an SDK for customers to embed in their apps so it would require each customer to apply for this entitlement - we have already tried to suggest this to affected customers but it is not ideal (e.g., customers end up in discussions with Apple tech support trying to convince them to use the modern non-BSD APIs, something they have no control over given the problem at hand).

If you insist on working with IP addresses then you take on the burden of implementing Happy Eyeballs, which is not fun (especially with UDP).

We have done just that and it is working fine (modulo the general iOS 14.5 hassle).

Coming back to your question about resolving a service, this is a known hole in the Network framework story right now (r. 73266838). There are two ways to get around this [...]

Thanks for the pointers, we will take a look! That is - do these APIs also require the multicast entitlement? We are only browsing for specific custom domains.

Ulrik

I assume you mean it works fine if the multicast entitlement is applied?

Correct.

customers end up in discussions with Apple tech support trying to convince them to use the modern non-BSD APIs

Or, indeed, trying to convince them to stop embedding their own mDNS resolver, which is the fundamental problem here. You really shouldn’t be sending folks down that path.

do these APIs also require the multicast entitlement?

No. See FAQ-3 is the Local Network Privacy FAQ.

Having said that, using Bonjour has its own local network privacy implementations; see FAQ-2.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Obtaining IP and port number of local services with iOS 14.5
 
 
Q