RFC 2168

Resolution of Uniform Resource Identifiers using the Domain Name System

๐Ÿ“… published June 1997, from ietf

RFC 2168 ๐ŸŽ€ Network Working Group ๐ŸŒธ Category: Experimental (so it's not a standard, no cap) ๐Ÿงช Date: June 1997 ๐Ÿ“… Authors: R. Daniel from Los Alamos National Laboratory and M. Mealling from Network Solutions, Inc. ๐Ÿซถ Obsoletes / Updates: the title block doesn't list either, so there's nothing to chase there ๐Ÿฆ‹

Resolution of Uniform Resource Identifiers using the Domain Name System โœจ

Status of this Memo ๐Ÿ“

This memo defines an Experimental Protocol for the Internet community. โœจ It does not specify an Internet standard of any kind, so please don't call it one ๐Ÿ’… Discussion and suggestions for improvement are requested, so bring your takes ๐Ÿซถ Distribution of this memo is unlimited ๐ŸŒธ

Abstract ๐Ÿ”ฎ

URLs are literally the foundation of the World Wide Web, and they're a vital Internet technology ๐Ÿ‘‘ But they've been kinda brittle in practice ๐Ÿ’€ The core problem is that a URL usually points at a particular path to a file on a particular host. Once a URL has been handed out, there's no graceful way to change that path or host. There's also no graceful way to replicate the resource behind the URL for better network utilization and/or fault tolerance. Uniform Resource Names (URNs) were hypothesized as an adjunct to URLs that would fix all of that. URNs and URLs are both instances of a broader class of identifiers called Uniform Resource Identifiers (URIs) ๐Ÿฆ‹

The requirements doc for URN resolution systems[15] defines the concept of a "resolver discovery service." This document describes the first, experimental, RDS. It's implemented by a new DNS Resource Record called NAPTR (Naming Authority PoinTeR), which gives rules for mapping parts of URIs to domain names. ๐Ÿ—บ๏ธ By changing the mapping rules, we can change the host that gets contacted to resolve a URI. That means URLs can be handled way more gracefully over long time periods, and it forms the foundation for a new proposal for Uniform Resource Names ๐Ÿ’–

In addition to locating resolvers, the NAPTR provides for other naming systems to be grandfathered into the URN world ๐ŸŒˆ It also keeps the name assignment system independent from the resolution protocol system, and it allows multiple services (Name to Location, Name to Description, Name to Resource, ...) to be offered. โœจ With the SRV RR, the NAPTR record lets those services be replicated for fault tolerance and load balancing ๐Ÿ“

Introduction ๐Ÿงš

Uniform Resource Locators have been a significant advance in retrieving Internet-accessible resources. However, their brittle nature over time has been recognized for several years. ๐Ÿ’… The Uniform Resource Identifier working group proposed developing Uniform Resource Names to serve as persistent, location-independent identifiers for Internet resources, to overcome most of the problems with URLs. RFC-1737 [1] sets forth requirements on URNs. ๐Ÿ“‹

During the lifetime of the URI-WG, a bunch of URN proposals got generated. The developers of several of those proposals met in a series of meetings, and that resulted in a compromise known as the Knoxville framework. ๐Ÿค The major principle behind the Knoxville framework is that the resolution system must be separate from the way names are assigned. This is in marked contrast to most URLs, which identify the host to contact and the protocol to use. Readers are referred to [2] for background on the Knoxville framework and for additional information on the context and purpose of this proposal. ๐Ÿ“š

Separating the way names are resolved from the way they're constructed gives you several benefits. ๐ŸŽ€ It lets multiple naming approaches and resolution approaches compete, since different protocols and resolvers can be used. There's just one problem with that separation, though: how do we resolve a name when it can't give us directions to its resolver? ๐Ÿ˜ญ

For the short term, DNS is the obvious candidate for the resolution framework, since it's widely deployed and understood. ๐ŸŒ However, it's not appropriate to use DNS to maintain information on a per-resource basis. First of all, DNS was never intended to handle that many records. Second, the limited record size is inappropriate for catalog information. Third, domain names are not appropriate as URNs. ๐Ÿ™ˆ

So our approach is to use DNS to locate "resolvers" that can provide information on individual resources, potentially including the resource itself. ๐Ÿ” To do this, we "rewrite" the URI into a domain name following the rules provided in NAPTR records. Rewrite rules are super powerful, which matters when you're trying to meet the goals listed above. ๐Ÿ’ช However, collections of rules can get hard to understand. To lessen that problem, the NAPTR rules are always applied to the original URI, never to the output of previous rules. ๐Ÿ‘‘

Locating a resolver through the rewrite procedure may take multiple steps, but the beginning is always the same. โœจ The start of the URI gets scanned to extract its colon-delimited prefix. (For URNs, the prefix is always urn: and we extract the following colon-delimited namespace identifier [3].) NAPTR resolution begins by taking that extracted string, appending the well-known suffix .urn.net, and querying the DNS for NAPTR records at that domain name. ๐ŸŽฏ Based on the results of this query, zero or more additional DNS queries may be needed to locate resolvers for the URI. The details of the conversation between the client and the resolver thus located are outside the bounds of this draft. Three brief examples of this procedure are given in the next section. ๐Ÿฆ‹

The NAPTR RR provides the level of indirection needed to keep the naming system independent of the resolution system, its protocols, and its services. ๐Ÿงฉ Coupled with the new SRV resource record proposal[4], there's also the potential for replicating the resolver on multiple hosts, which overcomes some of the most significant problems of URLs. This is an important and subtle point! ๐Ÿคฏ Not only do the NAPTR and SRV records let us replicate the resource, we can replicate the resolvers that know about the replicated resource too. Preventing a single point of failure at the resolver level is a huge benefit. ๐Ÿซถ Separating the resolution procedure from the way names are constructed has additional benefits as well. Different resolution procedures can be used over time, and the ones that prove useful can be extended to deal with additional namespaces. ๐ŸŒˆ

Caveats โš ๏ธ

The NAPTR proposal is the first resolution procedure to be considered by the URN-WG. ๐Ÿ”Ž There are several concerns about the proposal, and those concerns motivated the group to recommend it for publication as an Experimental rather than a standards-track RFC.

First, URN resolution is new to the IETF, and we want to gain operational experience before recommending any procedure for the standards track. ๐Ÿงช Second, the NAPTR proposal is based on DNS and therefore inherits concerns about security and administration. The recent advancement of the DNSSEC and secure update drafts to Proposed Standard reduces these concerns, but we want to experiment with those new capabilities in the context of URN administration. ๐Ÿ” A third area of concern is the potential for a noticeable impact on the DNS. We believe the proposal makes appropriate use of caching and additional information, but it's best to go slow where the potential for impact on a core system like the DNS is concerned. ๐Ÿข Fourth, the rewrite rules in the NAPTR proposal are based on regular expressions. Since regular expressions are difficult for humans to construct correctly, there are concerns about the usability and maintainability of the rules. This is especially true where international character sets are concerned. ๐Ÿ˜ตโ€๐Ÿ’ซ Finally, the URN-WG is developing a requirements document for URN Resolution Services[15], but that document is not complete. That document needs to precede any resolution service proposals on the standards track. ๐Ÿ“Œ

Terminology ๐Ÿ“–

Here's what the key terms mean in this doc:

  • "Must" or "Shall" - Software that does not behave in the manner that this document says it must is not conformant to this document. ๐Ÿ’…
  • "Should" - Software that does not follow the behavior that this document says it should may still be conformant, but is probably broken in some fundamental way. ๐Ÿ’€
  • "May" - Implementations may or may not provide the described behavior, while still remaining conformant to this document. ๐ŸŒธ

A detailed description of the NAPTR RR is coming later ๐Ÿงš, but first here's a vibe check: a simple description of the record plus three examples of how it gets used ๐Ÿ’…โœจ

The key fields in the NAPTR RR are order, preference, service, flags, regexp, and replacement:

  • order ๐Ÿ‘‘ decides the order in which records MUST be processed when a single query returns multiple NAPTR records. Okay so, a naming authority might have handed a piece of its namespace to another agency, and evaluating the records in the correct order is necessary for that delegation to work properly ๐ŸŽ€
  • preference ๐ŸŒธ decides the order in which records SHOULD be processed when multiple NAPTR records have the same value of "order". This lets a service provider say which resolvers get contacted first, so that more capable machines get tried before less capable ones. Main character energy ๐Ÿ’–
  • service ๐Ÿฆ‹ names the resolution protocol and the resolution service(s) that will be available if the rewrite from the regexp or replacement fields is applied. Resolution protocols are the protocols you use to talk to a resolver, and they'll be specified in other documents, like [5]. Resolution services are operations like N2R (URN to Resource), N2L (URN to URL), N2C (URN to URC), and so on. These get discussed in the URN Resolution Services document[6], and how they behave in a particular resolution protocol will be in that protocol's spec (see [5] for a concrete example) ๐Ÿ”ฅ
  • flags ๐Ÿงš holds modifiers that change what happens in the next DNS lookup, usually to make things faster. Flags can also change how the other fields in the record get interpreted, so clients MUST skip NAPTR records that contain an unknown flag value. No cap, this one is important ๐Ÿ™ˆ
  • regexp ๐Ÿ’… is one of the two fields used for rewrite rules, and it's the core concept of the NAPTR record. It's a String holding a sed-like substitution expression. (The actual grammar for those substitution expressions comes later in this draft.) The substitution gets applied to the original URN to figure out the next domain name to query. The regexp field should be used when the domain name to generate depends on information inside the URI. If the next domain name is always known (which is expected to be super common ๐Ÿ“), the replacement field should be used instead.
  • replacement ๐Ÿซถ is the other field used for the rewrite rule. It's an optimization for when the next domain name is fixed instead of depending on what's in the URI. It's a domain name (and it can be compressed if a DNS sender knows the recipient can decompress names in this RR type's RDATA field). If the rewrite is more complex than a simple domain name swap, the replacement field should be set to . and the regexp field used instead ๐ŸŒˆ

Note that the client applies all the substitutions and performs all the lookups. They are not performed in the DNS servers. Also, the developers of this document believe that regexps should rarely be used ๐Ÿฅบ The replacement field seems adequate for the vast majority of situations. Regexps are only necessary when portions of a namespace are to be delegated to different resolvers. Finally, the regexp and replacement fields are, at present, mutually exclusive. However, developers of client software should be aware that a new flag might be defined that requires values in both fields ๐Ÿ‘€

Example 1

Consider a URN that uses the hypothetical DUNS namespace ๐Ÿ’ DUNS numbers identify approximately 30 million registered businesses around the world, and they're assigned and maintained by Dunn and Bradstreet. The URN might look like:

urn:duns:002372413:annual-report-1997

The first step in resolution is finding out about the DUNS namespace. The namespace identifier, "duns", gets extracted from the URN, prepended to urn.net, and then the NAPTRs for duns.urn.net get looked up. It might return records like this:

duns.urn.net
;;      order pref flags service          regexp        replacement
 IN NAPTR 100  10  "s" "dunslink+N2L+N2C" ""  dunslink.udp.isi.dandb.com
 IN NAPTR 100  20  "s" "rcds+N2C"         ""  rcds.udp.isi.dandb.com
 IN NAPTR 100  30  "s" "http+N2L+N2C+N2R" ""  http.tcp.isi.dandb.com

The order fields are all equal, which means no name delegation order has to be followed ๐Ÿซง The preference field tells us the provider would like clients to use the special dunslink protocol first, then the RCDS protocol, and HTTP is offered as a last resort ๐Ÿฅน Every record specifies the "s" flag, which we'll explain in a sec. The service fields say that if we speak dunslink, we can issue either an N2L or N2C request to get a URL or a URC (description) of the resource. The Resource Cataloging and Distribution Service (RCDS)[7] could be used to get a URC for the resource, while HTTP could be used to get a URL, a URC, or the resource itself ๐Ÿ’– Every record supplies the next domain name to query, so none of them need rewriting with regular expressions โœจ

The general case might need multiple NAPTR rewrites to find a resolver, but eventually we reach the "terminal NAPTR" ๐Ÿ Once we have the terminal NAPTR, our next probe into the DNS is for an SRV or A record instead of another NAPTR. Rather than probing for a NAPTR record that doesn't exist just to end the loop, the flags field is used to indicate a terminal lookup. If it has the value "s", the next lookup should be for SRV RRs, and "a" means A records should be sought. There's also a "p" flag to indicate the next action is Protocol-specific, but looking up another NAPTR won't be part of it ๐Ÿฆ‹

Since our example RR specified the "s" flag, it was terminal. Assuming our client doesn't know the dunslink protocol, our next action is to look up SRV RRs for rcds.udp.isi.dandb.com, which will tell us which hosts can provide the necessary resolution service. That lookup might return:

 ;;                          Pref Weight Port Target
 rcds.udp.isi.dandb.com IN SRV 0    0    1000 defduns.isi.dandb.com
                        IN SRV 0    0    1000 dbmirror.com.au
                        IN SRV 0    0    1000 ukmirror.com.uk

So we get three hosts that could actually do the resolution, plus the port we should use to talk to their RCDS server ๐ŸŽ€ (For how to interpret the fields above, check out the SRV proposal [4].)

There's a lot of room for optimization here ๐Ÿš€ We can return the SRV records as additional information for terminal NAPTRs, and the A records as additional information for those SRVs. Recursively providing additional information like this isn't explicitly blessed in the DNS specifications, but it isn't forbidden either, and BIND does take advantage of it [8]. It's a huge optimization. Combined with a long TTL for *.urn.net records, the average number of probes to DNS for resolving DUNS URNs would approach one ๐Ÿ˜ญ That's why DNS server implementors SHOULD provide additional information with NAPTR responses. The additional information will be either SRV or A records. If SRV records are available, their A records should be provided as recursive additional information ๐Ÿซถ

Note that the example NAPTR records above represent the reply the client will see. They aren't quite identical to what the domain administrator would put in the zone files. For one thing, the administrator should supply the trailing '.' character on any FQDNs ๐ŸŒธ

Example 2

Consider a URN namespace based on MIME Content-Ids ๐Ÿ’Œ The URN might look like this:

urn:cid:199606121851.1@mordred.gatech.edu

(This example is chosen for pedagogical purposes ๐ŸŽ“ and it doesn't conform to the recently-approved CID URL scheme.)

The first step in resolution is finding out about the CID namespace. The namespace identifier, cid, gets extracted from the URN, prepended to urn.net, and the NAPTR for cid.urn.net gets looked up. It might return records like this:

 cid.urn.net
  ;;       order pref flags service        regexp           replacement
   IN NAPTR 100   10   ""  ""  "/urn:cid:.+@([^\.]+\.)(.*)$/\2/i"    .

We only have one NAPTR response, so ordering the responses isn't a problem ๐Ÿ™Œ The replacement field is empty, so we check the regexp field and use the pattern provided there. We apply that regexp to the entire URN to see if it matches, and it does โœ… The \2 part of the substitution expression returns the string "gatech.edu". Since the flags field doesn't contain "s" or "a", the lookup isn't terminal, so our next probe to DNS is for more NAPTR records:

lookup(query=NAPTR, "gatech.edu").

Note that the rule doesn't extract the full domain name from the CID. Instead, it assumes the CID comes from a host and extracts that host's domain ๐Ÿซ While all hosts, like mordred, could have their very own NAPTR, maintaining those records for every machine at a site as large as Georgia Tech would be an intolerable burden ๐Ÿ˜ฉ Wildcards aren't appropriate here either, since they only return results when there are no exactly matching names already in the system.

The record returned from the query on "gatech.edu" might look like:

gatech.edu IN NAPTR
;;       order pref flags service           regexp  replacement
  IN NAPTR 100  50  "s"  "z3950+N2L+N2C"     ""    z3950.tcp.gatech.edu
  IN NAPTR 100  50  "s"  "rcds+N2C"          ""    rcds.udp.gatech.edu
  IN NAPTR 100  50  "s"  "http+N2L+N2C+N2R"  ""    http.tcp.gatech.edu

Continuing our example, the order and preference values are equal in every record, so the client is free to pick any of them ๐ŸŽฒ The flags field tells us these are the last NAPTR patterns we should see. After the rewrite (a simple replacement in this case), we should look up SRV records to get info on the hosts that can provide the necessary service ๐Ÿ’ซ

Assuming we prefer the Z39.50 protocol, our lookup might return:

 ;;                        Pref Weight   Port Target
 z3950.tcp.gatech.edu IN SRV 0    0      1000 z3950.gatech.edu
                      IN SRV 0    0      1000 z3950.cc.gatech.edu
                      IN SRV 0    0      1000 z3950.uga.edu

That gives us three hosts that could actually do the resolution, plus the port we should use to talk to their Z39.50 server ๐ŸŽ‰

Let's recall that the regular expression used \2 to extract a domain name from the CID, and . to match the literal '.' characters separating the domain name components ๐Ÿง  Since '' is the escape character, literal backslashes must be escaped by another backslash. For the cid.urn.net record above, the regular expression entered into the zone file should be "/urn:cid:.+@([^\.]+\.)(.)$/\2/i". When the client code actually receives the record, the pattern will have been converted to "/urn:cid:.+@([^.]+.)(.)$/\2/i" ๐Ÿซง

Example 3

Okay so even if URN systems were already everywhere, there would still be a tonne of URLs out there ๐Ÿ˜ญ๐ŸŒธ It should totally be possible to build a URN resolution system that also gives location independence to those URLs. This ties into the requirement in [1] to be able to grandfather in names from other naming systems, like ISO Formal Public Identifiers, Library of Congress Call Numbers, ISBNs, ISSNs, etc. ๐Ÿ“šโœจ

The NAPTR RR could also be used for URLs that already exist, no cap ๐Ÿฆ‹ Say we have the URL for a super popular piece of software that the publisher wants to mirror at a bunch of sites around the world:

http://www.foo.com/software/latest-beta.exe

We pull out the prefix, "http", and look up NAPTR records for http.urn.net. This might give back a record that looks like this:

http.urn.net IN NAPTR
;;  order   pref flags service      regexp             replacement
     100     90   ""      ""   "!http://([^/:]+)!\1!i"       .

This expression grabs everything after the first double slash and before the next slash or colon. ๐Ÿ™ˆ We use the '!' character to mark off the parts of the substitution expression, because otherwise we'd have to escape every forward slash with backslashes, and the regexp in the zone file would end up looking like "/http:\\/\\/([^\\/:]+)/\\1/i". Ew, messy bestie. ๐Ÿ’€

Applying this pattern to the URL pulls out "www.foo.com". Looking up NAPTR records for that might give:

www.foo.com
;;       order pref flags   service  regexp     replacement
 IN NAPTR 100  100  "s"   "http+L2R"   ""    http.tcp.foo.com
 IN NAPTR 100  100  "s"   "ftp+L2R"    ""    ftp.tcp.foo.com

Looking up SRV records for http.tcp.foo.com would tell you about the hosts that foo.com has picked to be its mirror sites. Then the client can choose one for the user. ๐ŸŽ€๐Ÿ’–

NAPTR RR Format โœจ

Here's the format of the NAPTR RR. The DNS type code for NAPTR is 35. ๐Ÿ”ข

Domain TTL Class Order Preference Flags Service Regexp
Replacement

Where:

  • Domain: The domain name this resource record refers to.
  • TTL: Standard DNS Time To Live field.
  • Class: Standard DNS meaning.
  • Order: A 16-bit integer specifying the order in which the NAPTR records MUST be processed to make sure portions of the namespace get delegated correctly over time. Low numbers are processed before high numbers, and once a NAPTR is found that "matches" a URN, the client MUST NOT consider any NAPTRs with a higher value for order. ๐Ÿšซ
  • Preference: A 16-bit integer that says what order NAPTR records with equal "order" values SHOULD be processed in, with low numbers processed before high numbers. It's kinda like the preference field in an MX record, and domain admins use it to point clients toward more capable hosts or lighter weight protocols. ๐Ÿงš
  • Flags: A String giving flags that control aspects of how the fields in the record get rewritten and interpreted. Flags are single characters from the set [A-Z0-9]. The case of the alphabetic characters doesn't matter. ๐ŸŒˆ
    • Right now only three flags are defined: "S", "A", and "P". "S" means the next lookup should be for SRV records instead of NAPTR records. "A" means the next lookup should be for A records. The "P" flag says the rest of the resolution shall be carried out in a Protocol-specific fashion, and we should not do any more DNS queries. ๐Ÿ™…โ€โ™€๏ธ
    • The other alphabetic flags are reserved. The numeric flags may be used for local experimentation. The S, A, and P flags are all mutually exclusive, and resolution libraries MAY signal an error if more than one is given. (Experimental code and code that helps make NAPTRs would be more likely to signal that error than a client like a browser.)
    • We expect multiple flags to be allowed in the future, so implementers MUST NOT assume the flags field can only ever contain 0 or 1 characters. ๐Ÿ‘€
    • If a client hits a record with an unknown flag, it MUST ignore it and move on to the next record. This test wins even over the "order" field. Since flags can control how fields get interpreted, a brand new flag could change how the regexp and/or replacement fields are read, so it might become impossible to tell whether a record matched a URN. ๐Ÿ’€
  • Service: Says which resolution service(s) are available down this rewrite path. It can also name the particular protocol used to talk to a resolver. A protocol MUST be specified if the flags field says the NAPTR is terminal. If a protocol is specified but the flags field doesn't say the NAPTR is terminal, the next lookup MUST be for a NAPTR. The client MAY choose not to do the next lookup if the protocol is unknown, but that behavior MUST NOT be relied upon. ๐Ÿซถ

The service field can take any of the values below (using the Augmented BNF of RFC 822[9]):

   service_field = [ [protocol] *("+" rs)]
   protocol      = ALPHA *31ALPHANUM
   rs            = ALPHA *31ALPHANUM
// The protocol and rs fields are limited to 32
// characters and must start with an alphabetic.
// The current set of "known" strings are:
// protocol      = "rcds" / "thttp" / "hdl" / "rwhois" / "z3950"
// rs            = "N2L" / "N2Ls" / "N2R" / "N2Rs" / "N2C"
//               / "N2Ns" / "L2R" / "L2Ns" / "L2Ls" / "L2C"

So basically it's an optional protocol followed by 0 or more resolution services, and each resolution service starts with a '+' character. โž•

Heads up, the empty string is also a valid service field! ๐Ÿ’… You'll usually see this at the top levels of a namespace, when there's no way to know what services and protocols a particular publisher will offer in that namespace.

Right now the known protocols are rcds[7], hdl[10] (binary, UDP-based protocols), thttp[5] (a textual, TCP-based protocol), rwhois[11] (textual, UDP or TCP based), and Z39.50[12] (binary, TCP-based). More will be allowed later. Protocol names have to be formed from the characters [a-Z0-9], and case doesn't matter. ๐Ÿ“

The service requests allowed right now will get more detail in [6], but in brief they are:

  • N2L - Given a URN, return a URL
  • N2Ls - Given a URN, return a set of URLs
  • N2R - Given a URN, return an instance of the resource.
  • N2Rs - Given a URN, return multiple instances of the resource, typically encoded using multipart/alternative.
  • N2C - Given a URN, return a collection of meta-information on the named resource. The format of this response is the subject of another document.
  • N2Ns - Given a URN, return all URNs that are also identifers for the resource.
  • L2R - Given a URL, return the resource.
  • L2Ns - Given a URL, return all the URNs that are identifiers for the resource.
  • L2Ls - Given a URL, return all the URLs for instances of of the same resource.
  • L2C - Given a URL, return a description of the resource.

The actual format of the service request and response gets decided by the resolution protocol, and that's covered in other documents (e.g. [5]). Protocols don't have to offer every service. The labels for service requests shall be formed from the set of characters [A-Z0-9], and case of the alphabetic characters doesn't matter. โœจ

  • Regexp: A STRING holding a substitution expression that gets applied to the original URI to build the next domain name to look up. The grammar for the substitution expression is in the next section. ๐Ÿ”
  • Replacement: The next NAME to query for NAPTR, SRV, or A records, depending on the value of the flags field. As mentioned above, this may be compressed. ๐Ÿ“ฆ

Substitution Expression Grammar: ๐Ÿ’…

The content of the regexp field is a substitution expression. True sed(1) substitution expressions aren't appropriate for this application for a bunch of reasons, so the contents of the regexp field MUST follow the grammar below:

   subst_expr   = delim-char  ere  delim-char  repl  delim-char  *flags
   delim-char   = "/" / "!" / ... (Any non-digit or non-flag character other
                  than backslash '\'. All occurances of a delim_char in a
                  subst_expr must be the same character.)
   ere          = POSIX Extended Regular Expression (see [13], section
                  2.8.4)
   repl         = dns_str /  backref / repl dns_str  / repl backref
   dns_str      = 1*DNS_CHAR
   backref      = "\" 1POS_DIGIT
   flags        = "i"
   DNS_CHAR     = "-" / "0" / ... / "9" / "a" / ... / "z" / "A" / ... / "Z"
   POS_DIGIT    = "1" / "2" / ... / "9"  ; 0 is not an allowed backref
value domain name (see RFC-1123 [14]).

The result of applying the substitution expression to the original URI MUST result in a string that follows the syntax for DNS host names [14]. Since the regexp field can be improperly specified, so that a non-conforming host name gets built, client software SHOULD verify the result is a legal host name before making queries on it. ๐Ÿง

Backref expressions in the repl portion of the substitution expression get replaced by the (possibly empty) string of characters enclosed by '(' and ')' in the ERE portion of the substitution expression. N is a single digit from 1 through 9, inclusive. It refers to the N'th backref expression, the one that starts with the N'th '(' and runs to the matching ')'. For example, the ERE

                   (A(B(C)DE)(F)G)
has backref expressions:
                   \1  = ABCDEFG
                   \2  = BCDE
                   \3  = C
                   \4  = F
              \5..\9  = error - no matching subexpression

The "i" flag means the ERE matching SHALL be performed in a case-insensitive fashion. Furthermore, any backref replacements MAY be normalized to lower case when the "i" flag is given. ๐Ÿฆ‹

The first character in the substitution expression shall be used as the character that delimits the components of the substitution expression. There must be exactly three non-escaped occurrences of the delimiter character in a substitution expression. Since escaped occurrences of the delimiter character get read as that character, digits MUST NOT be used as delimiters. Backrefs would get confused with literal digits if this were allowed. Similarly, if flags are specified in the substitution expression, the delimiter character must not also be a flag character. ๐Ÿšซ๐Ÿ”ข

Advice to domain administrators: ๐Ÿซถ

Okay bestie, let's talk about regular expressions ๐Ÿ’€. They're a pain to get right on their own, and then there's the DNS situation on top of that ๐Ÿ˜ญ. Any backslashes in a regexp have to be entered twice in a zone file so they show up once in a query response. Even worse, the need for double backslashes has probably not been tested by every DNS server implementor ๐Ÿ™ˆ. We expect urn.net to be the heaviest user of regexps. Only when you're delegating portions of a namespace should a typical domain administrator need to touch them ๐Ÿงš

Also, beware of the shell when you're messing with regexps from the command line ๐Ÿ“. Since '' is a super common escape character in shells, there's a good chance that when you think you're typing "\" you're actually typing "" ๐Ÿ˜ฉ. Similar caveats apply to characters such as

The "a" flag lets the next lookup be for A records instead of SRV records. There's no spot for a port number in the NAPTR record, so when the "A" flag is used, the specified protocol must be running on its default port ๐Ÿฆ‹

The URN Syntax draft defines a canonical form for each URN, and that form requires %encoding for characters outside a limited repertoire ๐Ÿ’…. The regular expressions MUST be written to operate on that canonical form. Since international character sets will end up using a lot of %encoded characters, regexps working on them will be essentially impossible to read or write by hand ๐Ÿ˜ญ๐Ÿซถ


Usage โœจ

For the edification of implementers, here's pseudocode for a client routine that uses NAPTRs ๐ŸŽ€. It's just a convenience and doesn't carry any weight as a standard way to process NAPTR records. Also, like all pseudocode, it has never been executed and may contain logical errors. You have been warned ๐Ÿ‘‘

    //
    // findResolver(URN)
    // Given a URN, find a host that can resolve it.
    //
    findResolver(string URN) {
      // prepend prefix to urn.net
      sprintf(key, "%s.urn.net", extractNS(URN));
      do {

        rewrite_flag = false;
        terminal = false;
        if (key has been seen) {
          quit with a loop detected error
        }
        add key to list of "seens"
        records = lookup(type=NAPTR, key); // get all NAPTR RRs for 'key'

        discard any records with an unknown value in the "flags" field.
        sort NAPTR records by "order" field and "preference" field
            (with "order" being more significant than "preference").
        n_naptrs = number of NAPTR records in response.
        curr_order = records[0].order;
        max_order = records[n_naptrs-1].order;

        // Process current batch of NAPTRs according to "order" field.
        for (j=0; j < n_naptrs && records[j].order <= max_order; j++) {
          if (unknown_flag) // skip this record and go to next one
             continue;
          newkey = rewrite(URN, naptr[j].replacement, naptr[j].regexp);
          if (!newkey) // Skip to next record if the rewrite didn't
             match continue;
          // We did do a rewrite, shrink max_order to current value
          // so that delegation works properly
          max_order = naptr[j].order;
          // Will we know what to do with the protocol and services
          // specified in the NAPTR? If not, try next record.
          if(!isKnownProto(naptr[j].services)) {
            continue;
          }
          if(!isKnownService(naptr[j].services)) {
            continue;
          }

          // At this point we have a successful rewrite and we will
          // know how to speak the protocol and request a known
          // resolution service. Before we do the next lookup, check
          // some optimization possibilities.

          if (strcasecmp(flags, "S")
           || strcasecmp(flags, "P"))
           || strcasecmp(flags, "A")) {
             terminal = true;
             services = naptr[j].services;
             addnl = any SRV and/or A records returned as additional
                     info for naptr[j].
          }
          key = newkey;
          rewriteflag = true;
          break;
        }
      } while (rewriteflag && !terminal);

      // Did we not find our way to a resolver?
      if (!rewrite_flag) {
         report an error
         return NULL;
      }


      // Leave rest to another protocol?
      if (strcasecmp(flags, "P")) {
         return key as host to talk to;
      }

      // If not, keep plugging
      if (!addnl) { // No SRVs came in as additional info, look them up
        srvs = lookup(type=SRV, key);
      }

      sort SRV records by preference, weight, ...
      foreach (SRV record) { // in order of preference
        try contacting srv[j].target using the protocol and one of the
            resolution service requests from the "services" field of the
            last NAPTR record.
        if (successful)
          return (target, protocol, service);
          // Actually we would probably return a result, but this
          // code was supposed to just tell us a good host to talk to.
      }
      die with an "unable to find a host" error;
    }

Notes: ๐Ÿ“

  • A client MUST process multiple NAPTR records in the order specified by the "order" field, and it MUST NOT simply use the first record that provides a known protocol and service combination ๐Ÿ”ฅ
  • If a record at a particular order matches the URI, but the client doesn't know the specified protocol and service, the client SHOULD continue to examine records that have the same order. The client MUST NOT consider records with a higher value of order ๐Ÿ’… This is what makes delegation of portions of the namespace work. The order field is what lets site administrators say "all requests for URIs matching pattern x go to server 1, all others go to server 2" ๐Ÿซถ (A match is defined as: 1) the NAPTR provides a replacement domain name, or 2) the regular expression matches the URN.)
  • When multiple RRs have the same "order", the client should use the value of the preference field to select the next NAPTR to consider. However, because of preferred protocols or services, estimates of network distance and bandwidth, etc., clients may use different criteria to sort the records ๐ŸŒˆ
  • If the lookup after a rewrite fails, clients are strongly encouraged to report a failure, rather than backing up to pursue other rewrite paths ๐Ÿ™…โ€โ™€๏ธ
  • When a namespace is to be delegated among a set of resolvers, regexps must be used. Each regexp appears in a separate NAPTR RR. Administrators should do as little delegation as possible, because of limitations on the size of DNS responses ๐Ÿ“
  • Note that SRV RRs impose additional requirements on clients โœจ

Acknowledgments: ๐Ÿซถ

The editors would like to thank Keith Moore for all his consultations during the development of this draft ๐Ÿ’– We'd also like to thank Paul Vixie for helping debug their implementation and for answering their questions. Finally, we want to acknowledge our enormous intellectual debt to the participants in the Knoxville series of meetings, as well as the participants in the URI and URN working groups ๐Ÿฆ‹

References: ๐Ÿ“š

  • [1] Sollins, Karen and Larry Masinter, "Functional Requirements for Uniform Resource Names", RFC-1737, Dec. 1994.
  • [2] The URN Implementors, Uniform Resource Names: A Progress Report, http://www.dlib.org/dlib/february96/02arms.html, D-Lib Magazine, February 1996.
  • [3] Moats, Ryan, "URN Syntax", RFC-2141, May 1997.
  • [4] Gulbrandsen, A. and P. Vixie, "A DNS RR for specifying the location of services (DNS SRV)", RFC-2052, October 1996.
  • [5] Daniel, Jr., Ron, "A Trivial Convention for using HTTP in URN Resolution", RFC-2169, June 1997.
  • [6] URN-WG, "URN Resolution Services", Work in Progress.
  • [7] Moore, Keith, Shirley Browne, Jason Cox, and Jonathan Gettler, Resource Cataloging and Distribution System, Technical Report CS-97-346, University of Tennessee, Knoxville, December 1996.
  • [8] Paul Vixie, personal communication.
  • [9] Crocker, Dave H. "Standard for the Format of ARPA Internet Text Messages", RFC-822, August 1982.
  • [10] Orth, Charles and Bill Arms; Handle Resolution Protocol Specification, http://www.handle.net/docs/client_spec.html
  • [11] Williamson, S., M. Kosters, D. Blacka, J. Singh, K. Zeilstra, "Referral Whois Protocol (RWhois)", RFC-2167, June 1997.
  • [12] Information Retrieval (Z39.50): Application Service Definition and Protocol Specification, ANSI/NISO Z39.50-1995, July 1995.
  • [13] IEEE Standard for Information Technology - Portable Operating System Interface (POSIX) - Part 2: Shell and Utilities (Vol. 1); IEEE Std 1003.2-1992; The Institute of Electrical and Electronics Engineers; New York; 1993. ISBN:1-55937-255-9
  • [14] Braden, R., "Requirements for Internet Hosts - Application and and Support", RFC-1123, Oct. 1989.
  • [15] Sollins, Karen, "Requirements and a Framework for URN Resolution Systems", November 1996, Work in Progress.

Security Considerations ๐Ÿ’€๐Ÿ”

The use of "urn.net" as the registry for URN namespaces is subject to denial of service attacks, as well as other DNS spoofing attacks ๐Ÿ˜ฑ The interactions with DNSSEC are currently being studied. It's expected that NAPTR records will be signed with SIG records once the DNSSEC work is deployed.

The rewrite rules make identifiers from other namespaces subject to the same attacks as normal domain names. Since they haven't been easily resolvable before, this may or may not be considered a problem ๐Ÿ™ˆ

Regular expressions should be checked for sanity, not blindly passed to something like PERL ๐Ÿšจ

This document has discussed a way of locating a resolver, but it hasn't discussed any detail of how communication with the resolver takes place. There are significant security considerations attached to that communication. Those considerations are outside the scope of this document, and must be addressed by the specifications for particular resolver communication protocols ๐Ÿ”ฅ

Author Contact Information: ๐Ÿ’Œ

   Ron Daniel
   Los Alamos National Laboratory
   MS B287
   Los Alamos, NM, USA, 87545
   voice:  +1 505 665 0597
   fax:    +1 505 665 4939
   email:  rdaniel@lanl.gov


   Michael Mealling
   Network Solutions
   505 Huntmar Park Drive
   Herndon, VA  22070
   voice: (703) 742-0400
   fax: (703) 742-9552
   email: michaelm@internic.net
   URL: http://www.netsol.com/
๐Ÿ“ฆ where this page comes from