RFC 8766

Discovery Proxy for Multicast DNS-Based Service Discovery

๐Ÿ“… published June 2020, from ietf

RFC 8766: Discovery Proxy for Multicast DNS-Based Service Discovery ๐Ÿ’–

Okay, title block tea โ˜• This one is by S. Cheshire from Apple Inc., dated June 2020. It's a Standards Track doc, so it's official spec energy ๐Ÿ‘‘. The ISSN is 2070-1721. The title block has no Obsoletes or Updates line, so it doesn't list any other RFCs it replaces or changes ๐Ÿซถ.

Abstract โœจ

So this doc defines a network proxy that uses Multicast DNS to automatically fill up the wide-area unicast Domain Name System namespace with records about devices and services it finds on the local link ๐ŸŒธ.

Status of This Memo ๐Ÿ“œ

Okay, the big deal: this is an Internet Standards Track document ๐Ÿ‘‘.

This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It has received public review and has been approved for publication by the Internet Engineering Steering Group (IESG). Further information on Internet Standards is available in Section 2 of RFC 7841.

Info about the current status of this document, any errata, and how to give feedback on it is at https://www.rfc-editor.org/info/rfc8766 ๐Ÿ”—.

Copyright (c) 2020 IETF Trust and the persons identified as the document authors. All rights reserved.

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as in effect on the date of publication of this document. Please review these documents carefully, because they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions, and they're provided without warranty as described in the Simplified BSD License ๐Ÿ“.

Table of Contents ๐Ÿ“š

   1.  Introduction
   2.  Operational Analogy
   3.  Conventions and Terminology Used in This Document
   4.  Compatibility Considerations
   5.  Discovery Proxy Operation
     5.1.  Delegated Subdomain for DNS-based Service Discovery Records
     5.2.  Domain Enumeration
       5.2.1.  Domain Enumeration via Unicast Queries
       5.2.2.  Domain Enumeration via Multicast Queries
     5.3.  Delegated Subdomain for LDH Host Names
     5.4.  Delegated Subdomain for Reverse Mapping
     5.5.  Data Translation
       5.5.1.  DNS TTL Limiting
       5.5.2.  Suppressing Unusable Records
       5.5.3.  NSEC and NSEC3 Queries
       5.5.4.  No Text-Encoding Translation
       5.5.5.  Application-Specific Data Translation
     5.6.  Answer Aggregation
   6.  Administrative DNS Records
     6.1.  DNS SOA (Start of Authority) Record
     6.2.  DNS NS Records
     6.3.  DNS Delegation Records
     6.4.  DNS SRV Records
     6.5.  Domain Enumeration Records
   7.  DNSSEC Considerations
     7.1.  Online Signing Only
     7.2.  NSEC and NSEC3 Records
   8.  IPv6 Considerations
   9.  Security Considerations
     9.1.  Authenticity
     9.2.  Privacy
     9.3.  Denial of Service
   10. IANA Considerations
   11. References
     11.1.  Normative References
     11.2.  Informative References
   Appendix A.  Implementation Status
     A.1.  Already Implemented and Deployed
     A.2.  Already Implemented
     A.3.  Partially Implemented
   Acknowledgments
   Author's Address

1. Introduction โœจ

Multicast DNS [RFC6762] and its best friend DNS-based Service Discovery [RFC6763] were created to give IP networking the easy setup and autoconfiguration that AppleTalk was famous for [RFC6760] [ZC] [ROADMAP] ๐Ÿ“.

For a small home network that's just a single link (or a few physical links bridged together so IP sees them as one logical link), Multicast DNS [RFC6762] is enough for client devices to look up the ".local" host names of their peers on that network, and to use Multicast DNS-based Service Discovery (DNS-SD) [RFC6763] to find services offered there ๐Ÿ .

For a bigger network made of multiple links connected with IP-layer routing instead of link-layer bridging, link-local Multicast DNS alone isn't enough. Link-local Multicast DNS packets, by design, don't get propagated onto other links ๐Ÿ™ˆ.

Using link-local multicast packets for Multicast DNS was a deliberate choice [RFC6762]. Even on a single link, multicast traffic is generally considered more expensive than unicast, because it hits many devices instead of just one recipient. On top of that, with some technologies like Wi-Fi [IEEE-11], multicast is inherently less efficient and less reliable than unicast: Wi-Fi multicast is sent at lower data rates and isn't acknowledged [MCAST]. Flooding all that expensive multicast across multiple links would make the traffic load even worse ๐Ÿ’€.

Splitting the network into lots of small links keeps expensive multicast traffic from spreading, but it limits how discoverable services are. At the other end of the spectrum, a very large local link with thousands of hosts gives better service discovery, but at the cost of more multicast traffic ๐Ÿ“‰.

Doing DNS-based Service Discovery with purely Unicast DNS is more efficient and doesn't need big multicast domains, but the relevant data has to be available in the Unicast DNS namespace. That namespace could fall within a traditionally assigned globally unique domain name, or it could be a private local unicast domain name such as ".home.arpa" [RFC8375] ๐ŸŒˆ.

The DNS-SD specification [RFC6763] has Section 10 ("Populating the DNS with Information"), which talks about the different ways a service's PTR, SRV, TXT, and address records can make their way into the Unicast DNS namespace. That includes manual zone file configuration [RFC1034] [RFC1035], DNS Update [RFC2136] [RFC3007], and proxies of various kinds ๐Ÿงš.

One option is to make the relevant data available in the Unicast DNS namespace through manual DNS configuration. This has been used for many years at IETF meetings to advertise the IETF terminal room printer. Details of this example are given in Appendix A of the Roadmap document [ROADMAP]. However, manual DNS configuration is labor intensive, error prone, and requires a reasonable degree of DNS expertise ๐Ÿ˜ฉ.

Another option is having the devices offering the services populate the Unicast DNS namespace themselves, using DNS Update [REG-PROT] [DNS-UL]. However, this requires configuring DNS Update keys on those devices, which has proven onerous and impractical for simple devices like printers and network cameras ๐Ÿ“ท.

So, to facilitate efficient and reliable DNS-based Service Discovery, we need a hybrid that combines the ease of use of Multicast DNS with the efficiency and scalability of Unicast DNS ๐Ÿ’–.

This document specifies a type of proxy called a "Discovery Proxy" that uses Multicast DNS [RFC6762] to discover Multicast DNS records on its local link on demand, and makes corresponding DNS records visible in the Unicast DNS namespace โœจ.

In principle, similar mechanisms could be defined for other local discovery protocols, by creating a proxy that (i) uses the protocol in question to discover local information on demand, and then (ii) makes corresponding DNS records visible in the Unicast DNS namespace. Such mechanisms for other local discovery protocols could be addressed in future documents ๐Ÿ”ฎ.

The design of the Discovery Proxy is guided by the previously published DNS-based Service Discovery requirements document [RFC7558] ๐Ÿ“.

In simple terms, you pick a descriptive DNS name for each link in an organization. Using a DNS NS record, responsibility for that DNS name is delegated to a Discovery Proxy physically attached to that link. When a remote client issues a unicast query for a name within the delegated subdomain, the normal DNS delegation mechanism sends that query to the Discovery Proxy, since it has been declared authoritative for those names. Now, instead of consulting a textual zone file on disk to find the answer like a traditional authoritative DNS server would, a Discovery Proxy checks its local link, using Multicast DNS, to find the answer to the question ๐Ÿฆ‹.

For fault tolerance reasons, there may be more than one Discovery Proxy serving a given link.

Note that the Discovery Proxy uses a "pull" model. Until some remote client has requested data, the local link is not queried using Multicast DNS. In the idle state, in the absence of client requests, the Discovery Proxy sends no packets and imposes no burden on the network. It operates purely "on demand" ๐Ÿ˜Œ.

An alternative proposal that has been discussed is a proxy that performs DNS updates to a remote DNS server on behalf of the Multicast DNS devices on the local network. The difficulty with this is that Multicast DNS devices don't routinely announce their records on the network. Generally, they remain silent until queried. This means that the complete set of Multicast DNS records in use on a link can only be discovered by active querying, not by passive listening. Because of this, a proxy can only know what names exist on a link by issuing queries for them. Since it would be impractical to issue queries for every possible name just to find out which names exist and which do not, there is no reasonable way for a proxy to programmatically learn all the answers it would need to push up to the remote DNS server using DNS Update. Even if such a mechanism were possible, it would risk generating high load on the network continuously, even when there are no clients with any interest in that data ๐Ÿ˜ต.

Hence, having a model where the query comes to the Discovery Proxy is much more efficient than a model where the Discovery Proxy pushes the answers out to some other remote DNS server ๐Ÿš€.

A client seeking to discover services and other information performs this by sending traditional DNS queries to the Discovery Proxy or by sending DNS Push Notification subscription requests [RFC8765].

How a client discovers what domain name(s) to use for its DNS-based Service Discovery queries (and, consequently, what Discovery Proxy or Proxies to use) is described in Section 5.2 ๐Ÿ—บ๏ธ.

The diagram below illustrates a network topology using a Discovery Proxy to provide discovery service to a remote client.

    +--------+   Unicast     +-----------+  +---------+  +---------+
    | Remote | Communication | Discovery |  | Network |  | Network |
    | Client |---- . . . ----|   Proxy   |  | Printer |  | Camera  |
    +--------+               +-----------+  +---------+  +---------+
         |                         |             |            |
   ------------            --------------------------------------------
                          Multicast-capable LAN segment (e.g., Ethernet)

                        Figure 1: Example Deployment

Note that there need not be any Discovery Proxy on the link to which the remote client is directly attached. The remote client communicates directly with the Discovery Proxy using normal unicast TCP/IP communication mechanisms, potentially spanning multiple IP hops, possibly including VPN tunnels and other similar long-distance communication channels ๐Ÿซถ.

2. Operational Analogy โœจ

okay so a Discovery Proxy is NOT a multicast relay or forwarder ๐Ÿ™…โ€โ™€๏ธ it doesn't forward any multicast packets at all, so there's zero risk of forwarding loops causing a traffic storm ๐Ÿ’€ (iykyk). instead it acts as a proxy for remote clients ๐Ÿซถ it does the queries on their behalf and then reports the results back to them. main character energy, fr.

think about calling a coworker when you're out of the office ๐Ÿ“ž you're like, "hey bestie, would you mind opening a printer browser window and telling me the names of the printers you see?" ๐Ÿ–จ๏ธ and nothing bad can happen there, because no multicast packets are sent over a phone call. no forwarding loop, no storm, just vibes ๐ŸŒธ

a similar version is where you skip the human middleman and log in to your own desktop work computer with screen sharing ๐Ÿ–ฅ๏ธ then you run the printer browser yourself and look at the list. or you log in with Secure Shell (ssh) and type dns-sd -B _ipp._tcp to see the printer names show up โœจ in both cases there's no risk of a forwarding loop causing a traffic storm either, because no multicast packets are being sent over the screen-sharing or ssh connection ๐Ÿ’…

the Discovery Proxy is just another way to do remote queries ๐Ÿฆ‹ it uses a different protocol instead of screen sharing or ssh. you can think of the Discovery Proxy mechanism as a custom Remote Procedure Call (RPC) protocol that lets a remote client use the Multicast DNS APIs on the Discovery Proxy device, the same way a local client running on that device would use them ๐Ÿงš

and here's the tea ๐Ÿ“ when the Discovery Proxy software does Multicast DNS operations, it gets the exact same Multicast DNS caching mechanisms that any other client on that device gets ๐Ÿ’œ it doesn't matter who's asking. it could be a printer browser running locally, a remote user running the printer browser over screen sharing, a remote user on ssh running a command-line tool like "dns-sd", or a remote user sending DNS requests that make a Discovery Proxy do discovery operations for them. same rules, same caching, no drama ๐Ÿ‘‘


3. Conventions and Terminology Used in This Document ๐ŸŽ€

the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here. ๐Ÿ”ฅ so the capital letters are doing the heavy lifting, bestie. lowercase ones are just regular words ๐Ÿ™ˆ

the Discovery Proxy builds on Multicast DNS, which works between hosts on the same link ๐Ÿ”— for this document, a set of hosts counts as "on the same link" if:

  • when any host from that set sends a packet to any other host in that set, using unicast, multicast, or broadcast, the entire link-layer packet payload arrives unmodified, and
  • a broadcast sent over that link, by any host from that set of hosts, can be received by every other host in that set.

the link-layer header is allowed to be modified, like in Token Ring Source Routing [IEEE-5] ๐Ÿงต but the link-layer payload is not. specifically, if any device forwarding a packet changes any part of the IP header or IP payload, then that packet is no longer considered to be on the same link ๐Ÿšซ so it can pass through things like repeaters, bridges, hubs, or switches and still count as on the same link for this document. but it can't go through something like an IP router that decrements the IP TTL or otherwise modifies the IP header ๐Ÿ’€


4. Compatibility Considerations ๐ŸŒˆ

no changes to existing devices are required to work with a Discovery Proxy ๐Ÿ™Œ the devices you already have just keep on living their best lives.

existing devices that advertise services using Multicast DNS work with a Discovery Proxy โœจ

existing clients that support DNS-based Service Discovery over Unicast DNS work with a Discovery Proxy too ๐Ÿ’– and this has been around forever: DNS-based Service Discovery over Unicast DNS was introduced in Mac OS X 10.4 Tiger in April 2005 ๐ŸŽ and it's been included in Apple products released since then, including the iPhone and iPad ๐Ÿ“ฑ it's also in products from other vendors, like Microsoft Windows 10 ๐ŸชŸ

if you want the big picture of the whole family of DNS-based Service Discovery technologies, and how the Discovery Proxy fits in with them, check out the Service Discovery Road Map document [ROADMAP] ๐Ÿ—บ๏ธ


5. Discovery Proxy Operation ๐Ÿฆ‹

in a typical setup, a Discovery Proxy is configured to be authoritative [RFC1034] [RFC1035] for four or more DNS subdomains, listed below ๐Ÿ“‹ authority for these subdomains gets delegated from the parent domain to the Discovery Proxy in the usual DNS delegation way, via NS records ๐Ÿ’…

  • A DNS subdomain for DNS-based Service Discovery records. this subdomain name may contain rich text, including spaces and other punctuation ๐ŸŽจ that's because it's only used in graphical user interfaces, where rich text is appropriate โœจ
  • A DNS subdomain for host name records. this subdomain name SHOULD be limited to letters, digits, and hyphens so host names are easy to use in command-line interfaces ๐Ÿ’ป
  • One or more DNS subdomains for IPv4 Reverse Mapping records. these subdomains have names that end in in-addr.arpa ๐Ÿ”„
  • One or more DNS subdomains for IPv6 Reverse Mapping records. these subdomains have names that end in ip6.arpa ๐Ÿ”

in an enterprise network, naming and delegating these subdomains is usually done by the network administrator taking deliberate action ๐Ÿข in a home network, it's usually handled by some automatic configuration mechanism, like the Home Networking Control Protocol (HNCP) [RFC7788] ๐Ÿ 

these three kinds of delegated subdomains (service discovery, host names, and reverse mapping) are described below in Sections 5.1, 5.3, and 5.4 ๐Ÿงšโ€โ™€๏ธ and how a client discovers where to send its DNS-based Service Discovery queries is covered in Section 5.2 ๐Ÿ”

5.1. Delegated Subdomain for DNS-based Service Discovery Records โœจ

okay so, in its simplest form, every link in an organization gets its own unique Unicast DNS domain name, like Building 1.example.com or 2nd Floor.Building 3.example.com ๐Ÿข. Grouping multiple links under one Unicast DNS domain name is going to be specified in a future companion document ๐Ÿ‘€, but for this document, just assume each link has its own unique name. In a GUI, these names won't show up as dotted strings like above. They'll look more like a file browser, with folders, subfolders, and files ๐Ÿ“, which is kinda hard to show in a text-only doc but totally iconic.

  +---------------+--------------+-------------+-------------------+
  | *example.com* |  Building 1  |  1st Floor  | Alice's printer   |
  |               |  Building 2  | *2nd Floor* | Bob's printer     |
  |               | *Building 3* |  3rd Floor  | Charlie's printer |
  |               |  Building 4  |  4th Floor  |                   |
  |               |  Building 5  |             |                   |
  |               |  Building 6  |             |                   |
  +---------------+--------------+-------------+-------------------+

                       Figure 2: Illustrative GUI

Each named link in an organization has one or more Discovery Proxies serving it ๐Ÿ’…. This Discovery Proxy function can be done by a device like a router or switch that's physically attached to that link. In the parent domain, NS records are used to delegate ownership of each defined link name (like Building 1.example.com) to one or more Discovery Proxies that serve that named link. So basically, the Discovery Proxies are the authoritative name servers for that subdomain ๐Ÿซถ. Just like the rest of DNS-based Service Discovery, all names are represented as-is using plain UTF-8 encoding, and as described in Section 5.5.4, no text-encoding translations are performed ๐ŸŒธ.

With appropriate VLAN configuration [IEEE-1Q], one single Discovery Proxy device could have a logical presence on many links and act as the Discovery Proxy for all of them ๐Ÿฆ‹. In that setup, the device has one physical Ethernet [IEEE-3] port configured as a VLAN trunk port, and it shows up to the software on that device as multiple virtual Ethernet interfaces, one connected to each VLAN link. It's giving multitasking queen ๐Ÿ‘‘.

Another option, instead of VLAN technology, is using a Multicast DNS Discovery Relay [RELAY], which is another way a Discovery Proxy can have a "virtual" presence on a remote link ๐Ÿงš.

When a DNS-SD client sends a Unicast DNS query to find services in a particular Unicast DNS subdomain (like _ipp._tcp.Building 1.example.com. PTR ?), normal DNS delegation forwards that query until it reaches the delegated authoritative name server for that subdomain, which is the Discovery Proxy on that link ๐ŸŽฏ. Like a regular Unicast DNS server, a Discovery Proxy speaks the usual Unicast DNS protocol [RFC1034] [RFC1035] over UDP and TCP. BUT here's the twist ๐Ÿ˜ญ: a normal Unicast DNS server generates answers from data in its manually configured zone file, while a Discovery Proxy learns its answers using Multicast DNS. It does this by checking its Multicast DNS cache and/or sending Multicast DNS queries, as appropriate under the usual Multicast DNS protocol rules [RFC6762], for the matching Multicast DNS name, type, and class. The delegated zone part of the name gets swapped with .local, so in this case it's _ipp._tcp.local. PTR ? ๐Ÿ“. Then, from the Multicast DNS data it gets back, the Discovery Proxy builds the right Unicast DNS response, with the .local top-level label of the owner name swapped back out for the delegated zone's name โœจ. More details on the name translation rules are in Section 5.5, and the rules for how long the Discovery Proxy waits to collect Multicast DNS responses before sending its unicast reply are in Section 5.6 โณ.

The existing Multicast DNS caching mechanism keeps unnecessary Multicast DNS queries off the wire ๐Ÿ™Œ. The Discovery Proxy is acting as a client of the underlying Multicast DNS subsystem, so it gets the same caching and efficiency perks as any other client using that subsystem. Lowkey genius.

Now, the contents of the delegated zone are generated by doing .local Multicast DNS queries, so they mirror the records on the local link pretty closely, but NOT perfectly ๐Ÿ™ˆ. It's not a full two-way match. Some records available via Multicast DNS might not have equivalents in the delegated zone, either because they're invalid or not relevant there, or because they're suppressed since they're unusable outside the local link (see Section 5.5.2). On the flip side, some records in the delegated zone might not have matching records on the local link via Multicast DNS. The big one is certain administrative SRV records (see Section 6), which logically live inside the delegated zone but actually describe metadata _about_ the zone rather than records _within_ it. So those administrative records don't have any counterparts in the Multicast DNS namespace of the local link. Not me being confused, it's just how it is ๐Ÿ’€.

5.2. Domain Enumeration ๐Ÿ—บ๏ธ

A DNS-SD client does Domain Enumeration [RFC6763] using certain PTR queries, both unicast and multicast ๐Ÿ“ก.

If a DNS-SD client gets a Domain Name configuration via DHCP, it sends unicast queries derived from that domain name. It also sends unicast queries using names derived from its IPv4 subnet address(es) and IPv6 prefix(es) ๐Ÿ’œ. These unicast Domain Enumeration queries are covered in Section 5.2.1. A DNS-SD client also sends multicast Domain Enumeration queries in the "local" domain [RFC6762], as described in Section 5.2.2. Then all the results of the Domain Enumeration queries get combined for DNS-based Service Discovery purposes ๐ŸŽ€.

5.2.1. Domain Enumeration via Unicast Queries ๐Ÿ’Œ

The administrator (human or automated) creates Unicast DNS Domain Enumeration PTR records [RFC6763] to tell clients which service discovery domains are available ๐Ÿ“ฃ. There are two kinds of these records: ones with names derived from the domain name sent to clients via DHCP option 15 [RFC2132], and ones with names derived from either the IPv4 subnet address(es) or IPv6 prefix(es) the clients are using ๐ŸŒˆ. Here's an example of the name-based kind, where the DHCP server gave the client the domain name "example.com":

      b._dns-sd._udp.example.com.    PTR   Building 1.example.com.
                                     PTR   Building 2.example.com.
                                     PTR   Building 3.example.com.
                                     PTR   Building 4.example.com.

      db._dns-sd._udp.example.com.   PTR   Building 1.example.com.

      lb._dns-sd._udp.example.com.   PTR   Building 1.example.com.

What these records mean is defined in the DNS-based Service Discovery spec [RFC6763], but I'm repeating it here for convenience ๐Ÿค“. The "b" ("browse") records tell the client device the list of browsing domains to show the user so they can pick one ๐Ÿ‘†. The "db" ("default browse") record tells the client which domain in that list should be picked by default. The "db" domain MUST be one of the domains in the "b" list. If it isn't, then no domain gets selected by default ๐Ÿšซ. The "lb" ("legacy browse") record tells the client device which domain to automatically browse for apps that don't have a UI for multi-domain browsing (which is most of them at the time of writing) ๐Ÿ’…. The "lb" domain is often the same as the "db" domain, or sometimes the "db" domain plus one or more others that should be on the automatic browsing list for legacy clients.

Heads up, bestie ๐Ÿšจ: in the example above, space characters are shown as actual spaces just so it's easier to read. If you're typing this data by hand into a textual zone file for authoritative server software like BIND, be careful ๐Ÿ˜ฌ. The space character is a field separator, and other characters like dot ('.'), semicolon (';'), dollar ('$'), backslash (''), and so on also have special meaning. These characters have to be escaped when they go into a textual zone file, following the rules in Section 5.1 of the DNS specification [RFC1035]. For example, a literal space in a name is written in the textual zone file as \032, so Building 1.example.com gets entered as Building\0321.example.com ๐Ÿ™ƒ.

DNS responses are capped at a maximum size of 65535 bytes ๐Ÿ“. That limits how many domains can come back for a Domain Enumeration query, and here's the math, babe ๐Ÿงฎ:

A DNS response header is 12 bytes. That's usually followed by a single qname (up to 256 bytes) plus qtype (2 bytes) and qclass (2 bytes), leaving 65275 for the Answer Section.

An Answer Section Resource Record consists of:

  • Owner name, encoded as a compression pointer, 2 bytes
  • RRTYPE (type PTR), 2 bytes
  • RRCLASS (class IN), 2 bytes
  • TTL, 4 bytes
  • RDLENGTH, 2 bytes
  • RDATA (domain name), up to 256 bytes

So each Resource Record in the Answer Section can take up to 268 bytes total, which means that in the worst case the Answer Section can hold no more than 243 domains ๐Ÿ˜ฑ.

In a more typical scenario, where the domain names aren't all maximum-sized and there's some similarity between names so reasonable name compression is possible, each Answer Section Resource Record may average 140 bytes. That means the Answer Section can contain up to 466 domains ๐Ÿง โœจ.

It's anticipated that this should be sufficient for even a large corporate network or university campus ๐Ÿซ๐Ÿ’–.

5.2.2. Domain Enumeration via Multicast Queries โœจ

okay so if Discovery Proxy stuff is everywhere in an enterprise, like there's a Discovery Proxy physically on every link, or a remote "virtual" presence on each link using VLANs or Multicast DNS Discovery Relays [RELAY], then bestie, this gives us another way to hand out Domain Enumeration config data to clients ๐Ÿซถ๐ŸŒธ

BUT the main job of a Discovery Proxy is helping remote clients find services on its own local link. This multicast thing is the side quest ๐Ÿ’… It publishes Domain Enumeration config over link-local multicast for the local clients on that link, and it usually points them at other faraway Discovery Proxies on other links. A client doesn't normally need the Discovery Proxy on its own link, because it can make its own Multicast DNS queries there. ๐Ÿฆ‹ The exception is when the local Wi-Fi access point is blocking or filtering local multicast traffic. Then even local clients need their local Discovery Proxy to do local discovery ๐Ÿ˜ญ

A Discovery Proxy can be set up to answer these Multicast DNS Domain Enumeration queries from clients:

b._dns-sd._udp.local.    PTR   ?
db._dns-sd._udp.local.   PTR   ?
lb._dns-sd._udp.local.   PTR   ?

This lets Discovery Proxies recommend browsing domains to DNS-SD clients on a per-link basis, which is so iconic ๐Ÿ’– In some enterprises, it may be preferable to give this per-link config as Discovery Proxy config data, instead of stuffing the same info into the Unicast DNS servers (in the "ip6.arpa" or "in-addr.arpa" domains). Both are valid vibes ๐ŸŒˆ

No matter how the network operator decides to deliver this config data, clients will do Domain Enumeration with both unicast and multicast queries, and then merge the results of those queries. Main character behavior ๐Ÿ‘‘


5.3. Delegated Subdomain for LDH Host Names

okay so DNS-SD service instance names and domains are allowed to contain arbitrary Net-Unicode text [RFC5198], encoded as precomposed UTF-8 [RFC3629]. Rich text, no notes ๐ŸŽ€

Users usually interact with service discovery software by looking at a list of discovered service instance names on screen and picking one by pointing, touching, or clicking. Same deal in software with a multi-domain DNS-SD interface: people see a list of offered domains and tap the one they want. ๐Ÿฆ‹ To use a service, nobody has to remember or type domain or instance names. They just need to recognize what's on the screen and click the thing they want, easy peasy โœจ

Host names are a different story, though. They get remembered and typed a lot ๐Ÿ˜ญ They've also historically shown up in command-line interfaces, where spaces can be a whole inconvenience. So host names have traditionally been limited to letters, digits, and hyphens (LDH), with no spaces or other punctuation. Very strict, very iconic ๐Ÿ’…

We do want rich text for DNS-SD service instance names and domains, but for maximum compatibility with how things are already used, it is advisable to keep host names to the traditional letter-digit-hyphen rules. So this service name:

"My Printer._ipp._tcp.Building 1.example.com"

is totally acceptable and desirable (in a graphical user interface it shows up as an instance called "My Printer" in the domain "Building 1" at "example.com" ๐Ÿ’–). But this host name:

"My-Printer.Building 1.example.com"

is less desirable, because of that space in "Building 1" ๐Ÿ™ˆ

To handle this difference in allowed characters, a Discovery Proxy SHOULD support having two separate subdomains delegated to it for each link it serves. One can contain arbitrary Net-Unicode text [RFC5198]. The second, more constrained subdomain can only contain letters, digits, and hyphens, and it's for host name records (the names of 'A' and 'AAAA' address records). The restricted names can be any valid name made of only letters, digits, and hyphens, including Punycode-encoded names [RFC3492]. ๐Ÿงš

For example, a Discovery Proxy could have the two subdomains "Building 1.example.com" and "bldg-1.example.com" delegated to it. The Discovery Proxy would then translate these two Multicast DNS records:

My Printer._ipp._tcp.local. SRV 0 0 631 prnt.local.
prnt.local.                 A   203.0.113.2

into these Unicast DNS records:

My Printer._ipp._tcp.Building 1.example.com.
                                  SRV 0 0 631 prnt.bldg-1.example.com.
prnt.bldg-1.example.com.     A   203.0.113.2

Notice the SRV record name uses the rich-text domain name ("Building 1.example.com"), while the address record name uses the LDH domain ("bldg-1.example.com") ๐Ÿซถ More details on the name translation rules are in Section 5.5.

A Discovery Proxy MAY support only a single rich-text Net-Unicode domain and use that domain for every record, including the 'A' and 'AAAA' address records. But if you go that route, know that it may produce host names that are awkward to use in command-line environments. Whether that's a problem depends on whether users in the target environment are expected to use command-line interfaces ๐Ÿ’€

A Discovery Proxy MUST NOT be restricted to support only a letter-digit-hyphen subdomain, because that results in an unnecessarily poor user experience. Not it being a letters-only sad girl ๐Ÿ™…โ€โ™€๏ธ

As described in Section 5.2.1, for clarity, the examples here show spaces in names as actual spaces. If this dynamically discovered data were ever manually typed into a textual zone file (which it isn't), spaces would need to be written as '\032'. So "My Printer._ipp._tcp.Building 1.example.com" would become "My\032Printer._ipp._tcp.Building\0321.example.com" ๐Ÿ“

The '\032' form never shows up in DNS messages sent over the air. On the wire, spaces are sent as spaces, not as '\032'. And in a graphical user interface on the client device, spaces show up as spaces too, not as '\032' โœจ


5.4. Delegated Subdomain for Reverse Mapping

okay so a Discovery Proxy can make managing reverse mapping domains way easier ๐ŸŒธ This is especially true for IPv6 addresses, where manual management can be more of a hassle than it is for IPv4 addresses.

To make this work, NS records in the parent domain are used to delegate ownership of the right reverse mapping domain to the Discovery Proxy. In other words, the Discovery Proxy becomes the authoritative name server for that reverse mapping domain ๐Ÿ‘‘ For fault tolerance reasons, there may be more than one Discovery Proxy serving a given link.

If a given link is using the IPv4 subnet 203.0.113/24, then the domain "113.0.203.in-addr.arpa" is delegated to the Discovery Proxy for that link.

If a given link is using the IPv6 prefix 2001:0DB8:1234:5678::/64, then the domain "8.7.6.5.4.3.2.1.8.b.d.0.1.0.0.2.ip6.arpa" is delegated to the Discovery Proxy for that link ๐Ÿงš

When a reverse mapping query shows up at the Discovery Proxy, it sends the identical query out on its local link as a Multicast DNS query. How you force an apparently unicast name to be resolved with link-local Multicast DNS depends on which API set you're using ๐Ÿฆ‹ For example, in the "dns_sd.h" APIs (available on macOS, iOS, Bonjour for Windows, Linux, and Android), using kDNSServiceFlagsForceMulticast tells the DNSServiceQueryRecord() call to do the query with Multicast DNS. Other API sets have their own ways of forcing multicast queries. When the host that owns that IPv4 or IPv6 address replies with a name of the form "something.local", the Discovery Proxy rewrites it to use its configured LDH host name domain instead of ".local", and then sends the response back to the caller ๐Ÿ’–

For example, a Discovery Proxy with the two subdomains "113.0.203.in-addr.arpa" and "bldg-1.example.com" delegated to it would translate this Multicast DNS record:

2.113.0.203.in-addr.arpa. PTR prnt.local.

into this Unicast DNS response:

2.113.0.203.in-addr.arpa. PTR prnt.bldg-1.example.com.

Here the "prnt.local" host name gets translated using the delegated LDH subdomain, as described in Section 5.5 ๐ŸŒˆ

Later queries for the prnt.bldg-1.example.com address record land inside the bldg-1.example.com domain, which is delegated to this Discovery Proxy. So they arrive at this Discovery Proxy, which answers them by issuing Multicast DNS queries and using the Multicast DNS answers it gets back to synthesize Unicast DNS responses, as described above. Full circle, bestie ๐Ÿซถ

Note that this description assumes every address on a given IPv4 subnet or IPv6 prefix is mapped to host names using the Discovery Proxy mechanism. It would be possible to build a Discovery Proxy that can be configured so some address-to-name mappings are done with Multicast DNS on the local link, while other address-to-name mappings inside that same IPv4 subnet or IPv6 prefix are configured manually. Mix and match, it's giving flexibility ๐Ÿ’œ

5.5. Data Translation ๐Ÿ”

okay so bestie, this is where the magic happens โœจ For the delegated rich-text and LDH subdomains, making the right Multicast DNS queries means translating from the configured DNS domain (like "Building 1.example.com") on the Unicast DNS side over to ".local" on the Multicast DNS side ๐ŸŽ€

For the delegated reverse-mapping subdomain, you make the right Multicast DNS queries by using the proper API mechanism to say "hey, do this one over Multicast DNS," as described in Section 5.4 ๐Ÿ’œ

Going the other way is just as important. Building the right Unicast DNS responses from the Multicast DNS answers means translating back from ".local" to the right configured Unicast DNS domain whenever it's needed, as described below ๐Ÿฆ‹

Here are the delegated subdomains we'll use in the examples ๐Ÿ‘‘

Delegated subdomain for rich-text names       Building 1.example.com.
Delegated subdomain for LDH names                 bldg-1.example.com.
Delegated subdomain for IPv4 reverse mapping  113.0.203.in-addr.arpa.

Names in Multicast DNS answers that don't end in ".local" need zero translation ๐Ÿ™Œ They're already good to go.

Names in Multicast DNS answers that DO end in ".local" only mean something on the local link ๐Ÿ  So they need translating before clients outside the link can actually use them ๐Ÿ˜ญ

Names ending in ".local" can show up in two places: as the owner names of received Multicast DNS answer records, and inside the RDATA of those records ๐Ÿงš

When a received Multicast DNS answer record has an owner name ending in ".local", you swap that ".local" top-level label for the name of the delegated subdomain that was used in the originating query ๐Ÿ’…

When a name inside the RDATA of a received Multicast DNS answer record ends in ".local", you translate it according to the delegated subdomain that was used in the originating query. More on that below ๐Ÿซถ

For queries in subdomains delegated for LDH host names, ".local" names in RDATA get translated into that delegated LDH subdomain. For example, a query for "thing.bldg-1.example.com" becomes a Multicast DNS query for "thing.local". If that query comes back with this CNAME record:

thing.local.               CNAME  prnt.local.

then both the owner name and the name in the RDATA get translated from ".local" to the LDH subdomain "bldg-1.example.com":

thing.bldg-1.example.com.  CNAME  prnt.bldg-1.example.com.

For queries in subdomains delegated for reverse mapping names, ".local" names in RDATA get translated to the delegated LDH subdomain if one is configured, or to the delegated rich-text subdomain otherwise. Picture a reverse mapping query that returns this PTR record ๐Ÿ”

2.113.0.203.in-addr.arpa.  PTR  prnt.local.

The owner name stays as it is, since it doesn't end in ".local" ๐Ÿ™ˆ The name in the RDATA gets translated from ".local" to the LDH subdomain "bldg-1.example.com":

2.113.0.203.in-addr.arpa.  PTR  prnt.bldg-1.example.com.

For queries in subdomains delegated for rich-text names, ".local" names in RDATA get translated depending on whether they represent host names, meaning RDATA names that are the owner names of A and AAAA DNS records ๐ŸŒˆ RDATA names ending in ".local" that represent host names go to the delegated LDH subdomain if one is configured, or to the delegated rich-text subdomain otherwise. Every other RDATA name ending in ".local" goes to the delegated rich-text subdomain. For example, say a DNS-SD service browsing PTR query returns this PTR record for IPP printing ๐Ÿ–จ๏ธ

_ipp._tcp.local.  PTR  My Printer._ipp._tcp.local.

Both the owner name and the name in the RDATA get translated from ".local" to the rich-text subdomain:

_ipp._tcp.Building 1.example.com.
                  PTR  My Printer._ipp._tcp.Building 1.example.com.

Now compare that with a query that returns this SRV record for one specific IPP printing instance ๐Ÿ“

My Printer._ipp._tcp.local.  SRV  0 0 631 prnt.local.

As with every query, the owner name gets translated to the delegated subdomain of the originating query, which here is the delegated rich-text subdomain "Building 1.example.com". But the ".local" name in the RDATA is the target host name field of an SRV record, and that field is used exclusively for host names ๐Ÿ’– So it gets translated to the LDH subdomain "bldg-1.example.com", if one is configured, instead of the rich-text subdomain:

My Printer._ipp._tcp.Building 1.example.com.
                             SRV  0 0 631 prnt.bldg-1.example.com.

There are other helpful translation and filtering operations too, described below ๐Ÿ’œ

5.5.1. DNS TTL Limiting โณ

For efficiency, Multicast DNS usually uses fairly high DNS TTL values ๐ŸŒธ For example, the typical TTL on DNS-SD service browsing PTR records is 75 minutes. What makes these high-ish TTLs okay is the cache coherency mechanisms built into the Multicast DNS protocol, which stop stale data from hanging around for too long ๐Ÿ›ก๏ธ When a service shuts down gracefully, it sends goodbye packets to remove its service browsing PTR record(s) right away from neighboring caches ๐Ÿ‘‹ If a service shuts down abruptly without sending goodbye packets, the Passive Observation Of Failures (POOF) mechanism described in Section 10.5 of the Multicast DNS specification [RFC6762] kicks in to purge the stale data from the cache ๐Ÿงน

A traditional Unicast DNS client on a distant remote link doesn't get to join in on these Multicast DNS cache coherency mechanisms on the local link ๐ŸŒ For traditional Unicast DNS queries (the ones received without using Long-Lived Queries (LLQ) [RFC8764] or DNS Push Notification subscriptions [RFC8765]), the DNS TTLs in the resulting Unicast DNS response MUST be capped at no more than ten seconds โฑ๏ธ

Negative responses get similar treatment: the negative caching TTL indicated in the SOA record [RFC2308] should also be ten seconds (see Section 6.1) ๐Ÿ’…

That ten-second number is picked based on user experience ๐Ÿฅน

Let's say a user is trying to reach a remote device, like a printer, and it fails because the device is powered off ๐Ÿ–จ๏ธ๐Ÿ’ค They then make a phone call and ask someone to turn it on. We want the device to become available to that user within a reasonable amount of time! It's reasonable to expect a simple device with a simple embedded operating system to take on the order of ten seconds to power on โšก Once the device is on and has announced itself on the network via Multicast DNS, we'd like it to take no more than another ten seconds for stale negative cache entries to expire from Unicast DNS caches. That way the device becomes available to the user who wants to reach it ๐ŸŽ‰

Similar reasoning applies to capping positive TTLs at ten seconds ๐Ÿง  If a device moves location, gets a new DHCP address, or goes through some other renumbering event, we want the updated info to reach remote clients in a fairly timely way ๐Ÿš€

Heads up though, network administrators: many recursive resolvers are configured by default to impose a minimum TTL of 30 seconds ๐Ÿ‘€ If stale data seems to be hanging around in the network to the point that it hurts user experience, administrators are advised to check the configuration of their recursive resolvers ๐Ÿ”ง

For received Unicast DNS queries that use LLQ [RFC8764] or DNS Push Notifications [RFC8765], the Multicast DNS record's TTL SHOULD be returned unmodified ๐Ÿฆ‹ That's because the notification channel exists to tell the remote client as records come and go! For more details on Long-Lived Queries and its newer replacement, DNS Push Notifications, see Section 5.6 โœจ

5.5.2. Suppressing Unusable Records ๐Ÿ™…โ€โ™€๏ธ

A Discovery Proxy SHOULD offer a configurable option, enabled by default, to suppress Unicast DNS answers for records that aren't useful outside the local link ๐Ÿซง When the option to suppress unusable records is turned on:

  • For a Discovery Proxy that is serving only clients outside the local link, DNS A and AAAA records for IPv4 link-local addresses [RFC3927] and IPv6 link-local addresses [RFC4862] SHOULD be suppressed ๐Ÿ™ˆ
  • Similarly, for sites that have multiple private address realms [RFC1918], in cases where the Discovery Proxy can determine that the querying client is in a different address realm, private addresses SHOULD NOT be communicated to that client ๐Ÿฐ
  • IPv6 Unique Local Addresses [RFC4193] SHOULD be suppressed in cases where the Discovery Proxy can determine that the querying client is in a different IPv6 address realm ๐ŸŒ™
  • By the same logic, DNS SRV records that reference target host names with no addresses usable by the requester should be suppressed, and likewise, DNS-SD service browsing PTR records that point to unusable SRV records should similarly be suppressed ๐Ÿงน

5.5.3. NSEC and NSEC3 Queries ๐Ÿ”Ž

Multicast DNS devices don't routinely announce their records on the network ๐Ÿคซ Generally, they stay quiet until someone queries them. This means the complete set of Multicast DNS records in use on a link can only be discovered by actively querying, not by passively listening ๐Ÿ‘‚ Because of that, a Discovery Proxy can only know which names exist on a link by issuing queries for them. And since it would be totally impractical to query every possible name just to figure out which exist and which don't, a Discovery Proxy can't programmatically generate the traditional Unicast DNS NSEC [RFC4034] and NSEC3 [RFC5155] records that assert the nonexistence of a large range of names ๐Ÿ˜ตโ€๐Ÿ’ซ

When queried for an NSEC or NSEC3 record type, the Discovery Proxy issues a qtype "ANY" query using Multicast DNS on the local link, then generates an NSEC or NSEC3 response with a Type Bit Map showing which record types do and don't exist for just that specific queried name, and no other names ๐ŸŽฏ

Multicast DNS NSEC records received on the local link MUST NOT be forwarded unmodified to a unicast querier ๐Ÿšซ Why? Because there are slight differences in the NSEC record data. In particular, Multicast DNS NSEC records don't have the NSEC bit set in the Type Bit Map, whereas conventional Unicast DNS NSEC records do have it set ๐Ÿง

5.5.4. No Text-Encoding Translation ๐Ÿ”ค

A Discovery Proxy does no translation between text encodings ๐Ÿ™…โ€โ™€๏ธ Specifically, it does no translation between Punycode encoding [RFC3492] and UTF-8 encoding [RFC3629], either in the owner name of DNS records or anywhere in the RDATA of DNS records. That includes the RDATA of PTR records, SRV records, NS records, and other record types like TXT, where it's ambiguous whether the RDATA may contain DNS names ๐ŸŒ€ All bytes are treated as-is, with no attempt at text-encoding translation ๐Ÿงƒ A client implementing DNS-based Service Discovery [RFC6763] will use UTF-8 encoding for its unicast DNS-based Service Discovery queries ๐Ÿ’œ The Discovery Proxy passes those through to the Multicast DNS subsystem without any text-encoding translation. Responses from the Multicast DNS subsystem come back the same way, without any text-encoding translation, to the requesting unicast client ๐Ÿซถ

5.5.5. Application-Specific Data Translation โœจ

okay so there may be cases where application-specific data translation is the move ๐Ÿ’…

take AirPrint printers. they tend to stuff their DNS-SD TXT record with super verbose info about what they can do ๐Ÿ™ˆ TXT records in the 500-1000 bytes range are not uncommon, and honestly that's a legacy thing from lineprinter (LPR) printing. LPR has no in-band capability negotiation, so all that info had to ride along in the DNS-SD TXT record instead. Internet Printing Protocol (IPP) printing does have in-band capability negotiation, but printers keep including the same capability info in their IPP DNS-SD TXT records anyway, just for convenience ๐Ÿซ 

on local Multicast DNS (mDNS) it's wasteful but not fatal. BUT when a Discovery Proxy collects data from multiple printers on a link and sends it back over unicast (via UDP or TCP), all that extra TXT junk can make the responses huge ๐Ÿ˜ญ a DNS reply over TCP with info about 70 printers at an average of 700 bytes each adds up to about 50 kilobytes of data. so a Discovery Proxy that actually understands an application-layer protocol like AirPrint (which uses IPP) can drop the unnecessary key/value pairs from the DNS-SD TXT record for better network efficiency ๐Ÿ“

also, a lot of printers have an "adminurl" key in their TXT record (for example, adminurl=http://printername.local/status.html). for that URL to be useful off the local link, the embedded ".local" host name has to be translated into a name with a bigger scope. translating ".local" names is easy when they show up in well-defined places: as a record's owner name, or in the domain name fields in the RDATA of record types like PTR and SRV. but in the printing case, the Discovery Proxy needs some application-specific knowledge about what the "adminurl" key means before it knows it contains a name that needs translating. this is kinda like why NAT gateways need ALGs (Application-Level Gateways) to correctly translate protocols that hide addresses in unexpected places ๐Ÿ•ต๏ธโ€โ™€๏ธ

so, to avoid needing app-specific knowledge about particular TXT record keys, protocol designers are advised to avoid putting link-local names or link-local IP addresses in TXT record keys if those would need translating for off-link operation. in the printing case, if the "adminurl" key doesn't get translated correctly, printing will still work from a different link, but clicking the "Admin" button will fail to open the printer's admin page ๐Ÿ’€ also, instead of copying the host name from the service's SRV record into the "adminurl" key (so the same host name shows up in two places), a better design might have been to leave the host name out of "adminurl" and let the client implicitly swap in the target host name from the SRV record. that way the host name only appears once, in a well-defined spot where software like the Discovery Proxy expects to find it โœจ

note that this kind of Application-Specific Data Translation is expected to be very rare. it's the exception, not the rule ๐ŸŽ€ this is a classic theme in computing: it's usually smart to start with a clean, layered design with clear boundaries. then, in certain special cases, you might break those layer boundaries when the performance and efficiency gains outweigh the inelegance of the layer violation ๐Ÿฆ‹

these layer violations are optional ๐Ÿซถ they're done mainly for efficiency and generally should not be needed for correct operation. a Discovery Proxy MAY operate purely at the mDNS layer, without knowing anything about DNS-SD semantics or anything above it. no pressure, bestie ๐Ÿ’œ


5.6. Answer Aggregation

okay this part is giving dilemma ๐Ÿ˜ฉ in a simple setup, you'd just gather multicast answers and forward them in a unicast response, easy. but then the big question is how long the Discovery Proxy should wait to be sure it got all the Multicast DNS answers it needs for a complete Unicast DNS response. wait too little and the response might be incomplete. wait too long and the client's user experience is trash ๐Ÿ’€ honestly there might not be any wait time that's short enough to feel good and long enough to reliably get complete results ๐Ÿ™ƒ

same vibes with TTLs. the Discovery Proxy (the authoritative name server for the subdomain in question) has to decide what DNS TTL to report for these records. if the TTL is too long, recursive resolvers answering their clients could cache stale data for way too long. if it's too short, the network traffic goes up more than necessary. and again, there might not be a TTL that's short enough to avoid stale data and long enough to be efficient on the network ๐Ÿ˜ตโ€๐Ÿ’ซ

BOTH of these dilemmas get solved by DNS Long-Lived Queries (LLQ) [RFC8764], or its newer replacement, DNS Push Notifications [RFC8765] โœจ๐Ÿ‘‘

clients supporting unicast DNS-based Service Discovery SHOULD implement DNS Push Notifications [RFC8765] for a better user experience ๐ŸŒˆ

clients and Discovery Proxies MAY support both LLQ and DNS Push Notifications. and when a client talks to a Discovery Proxy that supports both, it can use whichever protocol it likes. though it's expected that only DNS Push Notifications will stay supported in the long run ๐Ÿงš

here's the vibe when a Discovery Proxy gets a query using LLQ or DNS Push Notifications: it responds immediately with whatever Multicast DNS records it already has in its cache (if any). that gives a near-instant response, which is a huge win for the user ๐Ÿ”ฅ at the same time, the Discovery Proxy sends out a Multicast DNS query on the local link to find any extra Multicast DNS records it didn't already know about. if more Multicast DNS responses come in, they get delivered to the client in additional LLQ or DNS Push Notification update messages ๐Ÿ“ฌ how fast those updates show up is only limited by how fast the Multicast DNS device responds. fast device, fast update. slow device, slow update. the benefit here is that the Discovery Proxy can respond promptly, because it doesn't have to bundle all the results into one response that waits around for the expected worst-case delay in getting every Multicast DNS response ๐Ÿƒโ€โ™€๏ธ

now picture a proxy that only supports standard DNS queries. even if it tried to be reliable by assuming a super pessimistic worst-case time (which means a really bad user experience), there'd still be a risk that a slow Multicast DNS device takes even longer than that. imagine a device that isn't even powered on until ten seconds after the initial query arrives. the response would be incomplete ๐Ÿ˜ญ using update messages to deliver late replies fixes this dilemma: even very late responses aren't lost, they just come in a later update message ๐Ÿฅน

note that while normal DNS queries usually come through the client's configured recursive resolver, LLQ and DNS Push Notification subscriptions may be received directly from the client ๐Ÿ“ก

two factors decide how unicast responses get generated ๐Ÿง 

the first factor is whether or not the Discovery Proxy already has at least one record in its cache that answers the question.

the second factor is whether the client used a normal DNS query, or set up a subscription using LLQ or DNS Push Notifications. normal DNS queries are typically used for one-shot stuff like SRV or address record queries. LLQ and DNS Push Notification subscriptions are typically used for long-lived service browsing PTR queries. normal DNS queries and LLQ each have different response timing depending on cache state, which gives the first four cases below. DNS Push Notifications is the newer protocol and behaves the same no matter what's in the cache, which gives the fifth case ๐Ÿ’–

  • Standard DNS query; no answer in cache:

Issue an mDNS query on the local link, exactly like a local client would, for the desired record name, type, and class. include retransmissions as appropriate, following the established mDNS retransmission schedule [RFC6762]. the Discovery Proxy then waits for Multicast DNS responses ๐Ÿ‘€

as soon as any Multicast DNS response packet comes in with one or more positive answers to that question (with or without the Cache Flush bit [RFC6762] set), or a negative answer (signified via a Multicast DNS NSEC record [RFC6762]), the Discovery Proxy generates a Unicast DNS response message with the matching (filtered and translated) answers and sends it to the remote client โœ…

if no relevant Multicast DNS answers show up after six seconds, cancel the mDNS query and send a negative response to the remote client. six seconds is enough time for the underlying Multicast DNS subsystem to send out three mDNS queries and give responses some time to arrive โณ

(Reasoning: queries not using LLQ or Push Notifications are generally queries that expect an answer from only one device, so the first response is also the only response. ๐Ÿซถ)

DNS TTLs in responses MUST be capped to at most ten seconds.

  • Standard DNS query; at least one answer in cache:

No local mDNS queries are performed ๐Ÿ™…โ€โ™€๏ธ

the Discovery Proxy generates a Unicast DNS response message with the answer(s) from the cache right away, to keep delay to a minimum โšก

(Reasoning: queries not using LLQ or Push Notifications are generally queries that expect an answer from only one device. given RRSet TTL harmonization, if the proxy has one Multicast DNS answer in its cache, it can reasonably assume it has the whole set. ๐Ÿง )

DNS TTLs in responses MUST be capped to at most ten seconds.

  • Long-Lived Query (LLQ); no answer in cache:

same as the case above with no answer in the cache: plan to do mDNS querying for six seconds, and return an LLQ response message to the remote client as soon as any relevant mDNS response comes in ๐Ÿƒโ€โ™€๏ธ

if no relevant mDNS answers have arrived after six seconds, and the client hasn't cancelled its Long-Lived Query, return a negative LLQ response message to the remote client.

(Reasoning: we don't need to rush to send an empty answer ๐Ÿ™ˆ)

Regardless of whether or not a relevant mDNS response shows up within six seconds ๐Ÿ‘€, the Long-Lived Query stays active for as long as the client keeps its LLQ state ๐Ÿ’œ. It keeps sending mDNS queries until the Long-Lived Query gets cancelled. If the set of mDNS answers changes, LLQ Event Response messages get sent ๐Ÿฆ‹

DNS TTLs in responses are returned unmodified โœจ

  • Long-Lived Query (LLQ); at least one answer in cache:

Okay, this one is giving instant results ๐ŸŒธ As in the case above with at least one answer in the cache, the Discovery Proxy sends a unicast LLQ response with the answer(s) from the cache right away, so the delay is as small as possible ๐Ÿƒโ€โ™€๏ธ

The Long-Lived Query stays active for as long as the client keeps the LLQ state. It sends mDNS queries (with appropriate Known Answer lists) to check whether more answers are available ๐Ÿ” If the set of mDNS answers changes, LLQ Event Response messages get sent.

(Reasoning: We want a user interface that is displayed very rapidly yet continues to remain accurate even as the network environment changes. ๐ŸŽ€)

DNS TTLs in responses are returned unmodified ๐Ÿ’…

  • Push Notification Subscription

The Discovery Proxy acknowledges the subscription request immediately โšก

If one or more answers are already available in the cache, those answers get sent in an immediately following DNS PUSH message ๐Ÿ“ฌ

The Push Notification subscription stays active until the client cancels it. It keeps sending mDNS queries (with appropriate Known Answer lists) to see if more answers are available. If the set of mDNS answers changes, further DNS PUSH messages are sent ๐Ÿ’Œ

(Reasoning: We want a user interface that is displayed very rapidly yet continues to remain accurate even as the network environment changes. ๐ŸŽ€)

DNS TTLs in responses are returned unmodified.

Where the text above refers to returning "a negative response to the remote client", it is describing returning a "no error no answer" negative response, not NXDOMAIN. ๐Ÿ™ˆ This is because the Discovery Proxy cannot know all the Multicast DNS domain names that may exist on a link at any given time, so any name with no answers may have child names that do exist, which makes it an "empty non-terminal" name.

Note that certain aspects of the behavior described here do not have to be implemented overtly by the Discovery Proxy. They happen naturally as a result of using existing Multicast DNS APIs ๐Ÿงš

For example, in the first case above (standard DNS query and no answers in the cache), suppose a new Multicast DNS query is requested. That could come from a local client on the Discovery Proxy device, or from the Discovery Proxy software on that device acting for a remote client. If there is not already an identical Multicast DNS query active, and there are no matching answers already in the Multicast DNS cache on the Discovery Proxy device, then a series of Multicast DNS query packets gets issued with exponential backoff ๐Ÿ“ˆ The exponential backoff sequence in some implementations starts at one second and then doubles for each retransmission (0, 1, 3, 7 seconds, etc.). In others, it starts at one second and then triples for each retransmission (0, 1, 4, 13 seconds, etc.). In either case, if no response has been received after six seconds, that is long enough for the underlying Multicast DNS implementation to have sent three query packets without receiving any response. At that point, the Discovery Proxy cancels its Multicast DNS query (so no further Multicast DNS query packets will be sent for this query) and returns a negative response to the remote client via unicast ๐Ÿซถ

The six-second delay is chosen to be long enough to give devices enough time to respond, yet short enough not to be too annoying for a human user waiting for an answer โฑ๏ธ For example, using the "dig" DNS debugging tool, the current default settings make it wait a total of 15 seconds for a reply (three transmissions of the DNS UDP query packet, with a wait of 5 seconds after each packet). That is plenty of time to have received a negative reply from a Discovery Proxy after six seconds ๐Ÿ˜ญ

The text above states that for a standard DNS query, if at least one answer is already available in the cache, then a Discovery Proxy should not issue additional mDNS query packets. This also happens naturally as a result of using existing Multicast DNS APIs ๐ŸŒˆ If a new Multicast DNS query is requested (either locally, or by the Discovery Proxy on behalf of a remote client) for which there are relevant answers already in the Multicast DNS cache on the Discovery Proxy device, and the Multicast DNS query is immediately cancelled after the answers are delivered, then no Multicast DNS query packets will be generated for this query ๐Ÿ’–


6. Administrative DNS Records ๐ŸŽ€

6.1. DNS SOA (Start of Authority) Record ๐Ÿ“œ

The MNAME field SHOULD contain the host name of the Discovery Proxy device (i.e., the same domain name as the RDATA of the NS record delegating the relevant zone(s) to this Discovery Proxy device).

The RNAME field SHOULD contain the mailbox of the person responsible for administering this Discovery Proxy device.

The SERIAL field MUST be zero.

Zone transfers are undefined for Discovery Proxy zones, so the REFRESH, RETRY, and EXPIRE fields have no useful meaning for Discovery Proxy zones ๐Ÿ™ƒ These fields SHOULD contain reasonable default values. The RECOMMENDED values are: REFRESH 7200, RETRY 3600, and EXPIRE 86400.

The MINIMUM field (used to control the lifetime of negative cache entries) SHOULD contain the value 10. This value was chosen based on user-experience considerations (see Section 5.5.1) โณ

In the event that there are multiple Discovery Proxy devices on a link for fault tolerance reasons, clients will receive inconsistent SOA records (different MNAME and possibly RNAME) depending on which Discovery Proxy answers their SOA query. However, since clients generally have no reason to use the MNAME or RNAME data, this is unlikely to cause any problems ๐Ÿคทโ€โ™€๏ธ

6.2. DNS NS Records ๐Ÿงพ

In the event that there are multiple Discovery Proxy devices on a link for fault tolerance reasons, the parent zone MUST be configured with NS records giving the names of all the Discovery Proxy devices on the link.

Each Discovery Proxy device MUST be configured to answer NS queries for the zone apex name by giving its own NS record, and the NS records of its fellow Discovery Proxy devices on the same link, so that it can return the correct answers for NS queries.

The target host name in the RDATA of an NS record MUST NOT reference a name that falls within any zone delegated to a Discovery Proxy. Apart from the zone apex name, all other host names (names of A and AAAA DNS records) that fall within a zone delegated to a Discovery Proxy correspond to local Multicast DNS host names. Those logically belong to the respective Multicast DNS hosts defending those names, not the Discovery Proxy ๐Ÿ  Generally speaking, the Discovery Proxy does not own or control the delegated zone. It is merely a conduit to the corresponding .local namespace, which is controlled by the Multicast DNS hosts on that link. If an NS record were to reference a manually determined host name that falls within a delegated zone, that manually determined host name might inadvertently conflict with a corresponding .local host name owned and controlled by some device on that link ๐Ÿ’ฅ

6.3. DNS Delegation Records ๐Ÿšง

Since the Multicast DNS specification [RFC6762] states that there can be no delegation (subdomains) within a .local namespace, this implies that any name within a zone delegated to a Discovery Proxy (except for the zone apex name itself) cannot have any answers for any DNS queries for RRTYPEs SOA, NS, or DS. So:

  • for any query for the zone apex name of a zone delegated to a Discovery Proxy, the Discovery Proxy MUST generate the appropriate immediate answers as described above, and
  • for any query for any name below the zone apex, for RRTYPEs SOA, NS, or DS, the Discovery Proxy MUST generate an immediate negative answer.

6.4. DNS SRV Records ๐ŸŽ

There are certain special DNS records that logically fall within the delegated Unicast DNS subdomain. Rather than mapping to their corresponding .local namesakes, they actually contain metadata about how the delegated Unicast DNS subdomain itself operates. They do not exist in the corresponding .local namespace of the local link. For these queries, a Discovery Proxy MUST generate immediate answers, whether positive or negative, so clients don't sit around waiting for their query to be answered โšก

For example, if a Discovery Proxy implements Long-Lived Queries [RFC8764], then it MUST positively respond to _dns-llq._udp.<zone> SRV queries, _dns-llq._tcp.<zone> SRV queries, and _dns-llq-tls._tcp.<zone> SRV queries as appropriate. If it does not implement Long-Lived Queries, it MUST return an immediate negative answer for those queries. That way it won't pass those queries through to the local network as Multicast DNS queries and then wait unsuccessfully for answers that will never come ๐Ÿ™…โ€โ™€๏ธ

If a Discovery Proxy implements DNS Push Notifications [RFC8765], then it MUST positively respond to _dns-push-tls._tcp.<zone> queries. Otherwise, it MUST return an immediate negative answer for those queries ๐Ÿ“ฃ

A Discovery Proxy MUST return an immediate negative answer for _dns-update._udp.<zone> SRV queries, _dns-update._tcp.<zone> SRV queries, and _dns-update-tls._tcp.<zone> SRV queries. The reason is that using DNS Update [RFC2136] to change zones generated dynamically from local Multicast DNS data is not possible ๐Ÿšซ

6.5. Domain Enumeration Records ๐Ÿ—บ๏ธ

If the network operator chooses to use address-based unicast Domain Enumeration queries for client configuration (see Section 5.2.1), and the network operator also chooses to delegate the enclosing reverse mapping subdomain to a Discovery Proxy, then that Discovery Proxy becomes responsible for serving the answers to those address-based unicast Domain Enumeration queries ๐Ÿงญ

As with the SRV metadata records described above, a Discovery Proxy configured with delegated reverse mapping subdomains is responsible for generating immediate (positive or negative) answers for address-based unicast Domain Enumeration queries. It should not pass them through to the underlying Multicast DNS subsystem and then wait unsuccessfully for answers that will not be forthcoming ๐Ÿซ 

7. DNSSEC Considerations ๐Ÿ”

7.1. Online Signing Only ๐Ÿ–Š๏ธ

The Discovery Proxy acts as the authoritative name server for designated subdomains. If DNSSEC is to be used, the Discovery Proxy needs to possess a copy of the signing keys so it can generate authoritative signed data from the local Multicast DNS responses it receives ๐Ÿ”‘ Offline signing is not applicable to Discovery Proxy.

7.2. NSEC and NSEC3 Records โœจ

okay so in DNSSEC, NSEC and NSEC3 records are the ones that prove a name doesn't exist ๐Ÿ™ˆ This is called "authenticated denial of existence" [RFC4034] [RFC5155], and it's giving proof-of-absence energy ๐Ÿ’…

A Discovery Proxy only knows which names exist on the local link by asking for them, and it would be totally impractical to query every possible name just to figure out which ones are real ๐Ÿ˜ญ So a Discovery Proxy cannot programmatically synthesize the traditional NSEC and NSEC3 records that cover a big range of names. Instead, when it generates a negative response, it synthesizes a single NSEC record that denies just the specific name that was queried, and no others โœจ Since the Discovery Proxy has the zone signing key, it can do this on demand ๐Ÿ”‘ That NSEC only covers one name, so zone walking isn't a concern, and NSEC3 isn't necessary ๐Ÿ™Œ

Heads up, though: this only applies to traditional immediate DNS queries, which can return instant negative answers when there's no immediate positive answer โœจ With a DNS Push Notification subscription [RFC8765], there are no negative answers at all, just the absence of answers so far, which could change later if answers become available ๐Ÿฆ‹


8. IPv6 Considerations ๐Ÿงš

okay, so an IPv4-only host and an IPv6-only host basically behave as "ships that pass in the night" ๐Ÿšข Even if they're on the same Ethernet [IEEE-3], neither one has any clue what the other is sending ๐Ÿ‘€ That's why each link may have _two_ unrelated .local. zones: one for IPv4 and one for IPv6 ๐ŸŽ€ For practical purposes, a group of IPv4-only hosts and a group of IPv6-only hosts on the same Ethernet act like they're on two totally separate Ethernet segments, so it makes sense that they use the .local. zone exactly as they would if they really were on two separate segments ๐Ÿ’…

It will be desirable to have a mechanism that "stitches" these two unrelated .local. zones together so they look like one ๐Ÿงต That mechanism will need to tell apart a dual-stack (v4/v6) host that's in both .local. zones from two different hosts, one IPv4-only and one IPv6-only, that are both trying to use the same name(s) ๐Ÿ‘ฏ It's giving plot twist ๐Ÿ˜ญ This mechanism will be specified in a future companion document ๐Ÿ“š

For now, it is RECOMMENDED that a Discovery Proxy be configured with a single domain name for both the IPv4 and IPv6 .local. zones on the local link ๐ŸŒˆ Then, when a unicast query comes in, it should issue Multicast DNS queries using both IPv4 and IPv6 on the local link and combine the results โœจ


9. Security Considerations ๐Ÿ”ฅ

Security is where we get serious, bestie, so buckle up ๐Ÿซถ

9.1. Authenticity

A service proves it's present on a link by being able to answer link-local multicast queries on that link ๐Ÿ“ก If greater security is desired, then the Discovery Proxy mechanism should not be used, and something with stronger security should be used instead, such as authenticated secure DNS Update [RFC2136] [RFC3007] ๐Ÿ”

9.2. Privacy

The Domain Name System is, generally speaking, a global public database ๐ŸŒ Records in the DNS name hierarchy can be queried by name from, in principle, anywhere in the world ๐Ÿ‘€ If services on a mobile device (like a laptop computer) are made visible via the Discovery Proxy mechanism, then when those services show up in a domain like My House.example.com, it might tell (potentially hostile) observers that the mobile device is in the owner's home ๐Ÿ ๐Ÿ˜ฌ And when those services disappear from My House.example.com, observers could use that change to infer when the mobile device (and possibly its owner) may have left the house ๐Ÿšช The privacy of this info can be protected with techniques like firewalls, split-view DNS, and Virtual Private Networks (VPNs), which are customarily used today to protect the privacy of corporate DNS information ๐Ÿ›ก๏ธ

The privacy issue is particularly serious for the IPv4 and IPv6 reverse zones ๐Ÿšจ If the public delegation of the reverse zones points to the Discovery Proxy, and the Discovery Proxy is reachable globally, it could leak a significant amount of information ๐Ÿ˜ฑ Attackers could discover hosts that otherwise might not be easy to identify, and learn their host names ๐Ÿ•ต๏ธ They could also discover the existence of links where hosts frequently come and go ๐Ÿ’€

The Discovery Proxy could provide sensitive records only to authenticated users ๐Ÿ”‘ This is a general DNS problem, not one specific to the Discovery Proxy, and work is underway in the IETF to tackle it [RFC7626] ๐Ÿ› ๏ธ

9.3. Denial of Service

A remote attacker could send a rapid series of unique Unicast DNS queries to make a Discovery Proxy generate a rapid series of matching Multicast DNS queries on one or more of its local links ๐ŸŒช๏ธ Multicast traffic is generally more expensive than unicast traffic, especially on Wi-Fi links [MCAST], which makes this attack particularly serious ๐Ÿ˜ญ To limit the damage from these attacks, a Discovery Proxy (or the underlying Multicast DNS subsystem that it uses) MUST implement Multicast DNS query rate limiting appropriate to the link technology in question ๐Ÿšฆ For today's 802.11b/g/n/ac Wi-Fi links (where approximately 200 multicast packets per second is enough to consume approximately 100% of the wireless spectrum), a limit of 20 Multicast DNS query packets per second is RECOMMENDED ๐Ÿ“ถ On other link technologies like Gigabit Ethernet, higher limits may be appropriate ๐Ÿš€

Heads up: a side effect of this rate limiting is that a rogue remote client could send an excessive number of queries and cause a denial of service for other legitimate remote clients trying to use that Discovery Proxy ๐Ÿ˜ค However, this is still preferable to a rogue remote client being able to inflict even greater harm on the local network, which could break the correct operation of all local clients on that network ๐Ÿซ 

10. IANA Considerations

This document has no IANA actions ๐ŸŒธ


11. References

11.1. Normative References

11.2. Informative References ๐Ÿ“š

Okay bestie, these are the background reads ๐Ÿค“. You don't need them to get the spec, but they're the good context, and the IEEE standards, drafts, and RFCs are all right here. ๐ŸŒธ


Appendix A. Implementation Status โœจ

Some parts of the mechanism in this document are already out there in deployed software ๐Ÿ’ฟ, and some parts are brand new ๐Ÿ†•. This section spills the tea on which is which. ๐Ÿซถ

A.1. Already Implemented and Deployed

Domain enumeration by the client (the b._dns-sd._udp.<zone> queries) is already implemented and deployed. ๐Ÿ™Œ

Performing unicast queries to the indicated discovery domain is also already implemented and deployed. ๐Ÿ’–

Both of these are live in Mac OS X 10.4 Tiger and later (that includes every version of Apple iOS, on all models of iPhones, iPads, Apple TVs and HomePods ๐Ÿ“ฑ), in Bonjour for Windows, and in Android 4.1 "Jelly Bean" (API Level 16) and later. Iconic lineup, no cap ๐Ÿ‘‘.

Domain enumeration and unicast querying have been quietly doing their thing for years at IETF meetings, making the terminal room printers findable from outside the terminal room ๐Ÿ–จ๏ธ. So when an IETF attendee hits "Cmd-P" on a Mac, or picks AirPrint on an iPad or iPhone, and the terminal room printers pop up, it's because the client is sending Unicast DNS queries to the IETF DNS servers. The walk-through with the details of this exact example is in Appendix A of the Roadmap document [ROADMAP]. Main character energy, literally ๐Ÿ’….

The Long-Lived Query mechanism [RFC8764] referenced in this specification exists and is deployed, but the IETF never standardized it. ๐Ÿฅฒ The IETF has since made a superior Long-Lived Query mechanism called DNS Push Notifications [RFC8765], which is built on DNS Stateful Operations [RFC8490]. DNS Push Notifications is implemented and deployed in Mac OS X 10.15 and later, and iOS 13 and later. The upgrade is giving glow-up ๐Ÿฆ‹โœจ.

A.2. Already Implemented

A minimal, portable Discovery Proxy implementation was produced by Markus Stenberg and Steven Barth. It runs on OS X and several Linux variants including OpenWrt [OHP], and it was demonstrated at the Berlin IETF in July 2013. ๐Ÿงš

Tom Pusateri has an implementation that runs on any Unix/Linux system. It has a RESTful interface for management, plus an experimental demo command-line interface (CLI) and web interface. ๐Ÿ“

Ted Lemon also produced a portable implementation of Discovery Proxy, which is available in the mDNSResponder open source code. ๐Ÿ’œ

A.3. Partially Implemented

At the time of writing, existing APIs make multiple domains visible to client software, but most client user interfaces lump all discovered services into a single flat list. ๐Ÿ˜ฉ This is largely a chicken-and-egg problem. Application writers were understandably reluctant to spend time on domain-aware user interface code when few customers would benefit from it. If Discovery Proxy deployment becomes common, then application writers will have a reason to provide a better user experience. Existing applications will keep working with the Discovery Proxy but will show all services in a single flat list, while applications with improved user interfaces will show services grouped by domain. Soon, bestie ๐ŸŒˆ.

Acknowledgments

Thanks to Markus Stenberg for helping develop the policy on the four styles of unicast response, based on what data is immediately available in the cache. ๐Ÿซถ Thanks also to Anders Brandt, Ben Campbell, Tim Chown, Alissa Cooper, Spencer Dawkins, Ralph Droms, Joel Halpern, Ray Hunter, Joel Jaeggli, Warren Kumari, Ted Lemon, Alexey Melnikov, Kathleen Moriarty, Tom Pusateri, Eric Rescorla, Adam Roach, David Schinazi, Markus Stenberg, Dave Thaler, and Andrew Yourtchenko for their comments. The whole squad showed up ๐Ÿ’–๐Ÿ‘‘.

Author's Address

Stuart Cheshire Apple Inc. One Apple Park Way Cupertino, California 95014 United States of America

Phone: +1 (408) 996-1010 Email: cheshire@apple.com

๐Ÿ“ฆ where this page comes from